Compare commits

...

62 Commits

Author SHA1 Message Date
9f53b07491 misc: chore: Fix shader cache & CPU cache being in different folders on non-Windows
fixes #565
2025-01-22 08:52:21 -06:00
cd8113dadf misc: chore: Collapse adding a game/autoload dir into a single reusable method. 2025-01-21 18:59:56 -06:00
9089c4ffe5 misc: chore: Multi/Single file/folder picker extensions (for convenience)
The result of these extensions is an empty Optional when the user hits Cancel on the shown file picker.
2025-01-21 18:59:19 -06:00
fe9d8d05bd UI: Fixed the Amiibo keybind only working when the UI had been updated. 2025-01-21 18:00:51 -06:00
880a8ae748 misc: chore: Remove duplicated styling blocks in MainMenuBarView in favor of a reusable Avalonia Style. 2025-01-21 17:50:55 -06:00
11531dacb6 UI: Option to automatically Hide UI when game launches (#462)
Quality of life feature
Similar in function to the "Start Games in Fullscreen" toggle
For users who want to run games in windowed/non-fullscreen mode with
menu UI hidden, this eliminates the need to always click "Hide UI"
2025-01-21 17:36:51 -06:00
3974739ed3 More descriptive classification 2025-01-21 17:35:22 -06:00
440a3447fb docs: compat: Update South Park: The Fractured but Whole: playable -> boots 2025-01-21 17:10:54 -06:00
65374ed6cb UI: [ci skip] clarify dirty hacks subtext 2025-01-21 16:57:05 -06:00
789d6ab959 misc: chore: Improve autoloading DLC/updates logging, deliberately switch to Vulkan if Metal was somehow chosen on a non-mac system, add logger lines in the updater, cleanup enabled logs printing 2025-01-21 14:59:08 -06:00
182db31343 metal: Added Persona 4 Arena Ultimax to Auto 2025-01-21 14:07:05 -06:00
ea296b134d Use specific Ubuntu version in build script 2025-01-21 14:05:49 -06:00
bf584442b2 misc: chore: remove needless call to string.Format 2025-01-21 14:05:49 -06:00
cb7c294dbf Add more games to metal game list (#558)
Link's awakening I have played through most of the game with 0 issues.

In LEGO City undercover I have played multiple missions and explored the
map, I was unable to spot any issue. Except shadows flickering
sometimes, but that seems to happen on Vulkan and the PC version as well
and is propably normal.

Bayonetta seems to work flawless so far.

In Fast RMX, some tracks have flickering issues, like the second track
of the first cup. This happens on Vulkan as well.

-

Mario Bros. Wonder has following issues:

Overall issues:
- Sometimes there is short white flickering/artifacts, but they happen
on Vulkan as well.

Metal specific issue:
- In 2 underwater levels, a specific location causes a FPS drop not
present on Vulkan. But this is very minor and on all current M chips you
get on average better FPS with Metal (On my M3, there are occasional
drops that are worse with Vulkan), reducing stutter quite noticeably,
which is why I think it should get added to auto regardless.

- Isaac mentioned there is a issue in level 2, where the flowers singing
desync somehow. However, I was after lot of testing unable to replicate
this issue at all. More testing could be useful.

Fix: Fixed 2 typos in the comments
2025-01-21 14:05:41 -06:00
eaf1e7efd2 Cleanup in TitleIDs.cs (#546)
Just a little cleanup in TitleID.cs, adding a franchise title to most
franchises + sorting in alphabetical on all games.
2025-01-21 11:20:43 -06:00
471e7ed2e4 Add TitleID sort method (#553)
Adds an additional application list sorting method for the TitleID. A
bit of a niche choice for sorting but I think the TID is a relevant
enough piece of metadata that it should be there. (And I personally
would be using it)

- Using existing TitleId constant in ApplicationSort, implying this was
meant to be in the sorting options at some point?
- Reuses the "DlcManagerTableHeadingTitleIdLabel" locale for fulfilling
the need already, might be better to make a unique one for this in the
long run but this codebase is new to me so I wanted to make the changes
as unobtrusive as possible
- Using app.Id for the comparer seems to work fine, not sure if using
something else like IdString would be better?
2025-01-21 11:06:40 -06:00
ad3e80b383 Log .NET runtime version (#552)
I was looking into a crash, and found out it was an issue that was fixed
in .NET 9.0.1. Since Ryujinx embeds the runtime into the executable, it
not obvious which runtime a build uses. This logs the .NET runtime
version immediately after the build version.
2025-01-20 19:19:19 -06:00
ed64a63094 UI: Visually merge "Actions" and "Tools" menu bar items into Actions
The contents of the menu item are dependent on whether you're in a game.
No functionality has been removed.
2025-01-20 16:56:05 -06:00
8df7ba2d56 i18n: Norwegian DLC RomFS dumping translation 2025-01-20 15:55:37 -06:00
e743d78115 Add/fix service reported info (#551)
fixes the GetConfig service call, which now returns success correctly
adds support for getting the device serial number (which is fake and
reports as "RYU00000000000")
2025-01-20 14:59:54 -06:00
04ba762710 UI: Move DLC RomFS dumping under normal RomFS dumping.
Also removed it from DLC manager.
2025-01-20 14:30:28 -06:00
f42b2ed59d misc: chore: more correct last used user checking 2025-01-20 13:33:59 -06:00
d135385cab Leftovers, oops 2025-01-20 09:32:38 -06:00
b360f4e721 UI: Dump DLC RomFS.
You can access this in the Manage DLC screen, it's the new button on each DLC line.

Closes #548
2025-01-20 09:28:58 -06:00
a1c0c70ec2 Added missing TitleIDs (#545)
Added the remaining missing TitleIDs in the compat.csv list.
Excluding Homebrew apps.
2025-01-19 21:15:46 -06:00
290ac405ac Updated Ukrainian translation by Rondo (#543)
Co-authored-by: rrondo <46533574+rrondo@users.noreply.github.com>
2025-01-19 21:00:40 -06:00
bbd64fd5f0 misc: chore: Cleanup AppletMetadata usage 2025-01-19 19:40:49 -06:00
09446fd80e [ci skip] infra: Update copyright year in shortcut plist 2025-01-19 18:57:05 -06:00
4f014a89cf docs: compat: Donkey Kong Country Returns HD 2025-01-19 18:28:43 -06:00
6482e566ab UI: Compat: Unload compatibility entries when the window closes. 2025-01-19 17:41:50 -06:00
7fcd9b792e UI: Compat: Update owned game title IDs when ApplicationLibrary app count updates 2025-01-19 17:41:31 -06:00
e676fd8b17 UI: misc: simplify Intel Mac warning logic 2025-01-19 14:42:15 -06:00
dd16e3cee1 misc: chore: very small cleanup in AvaHostUIHandler 2025-01-19 13:18:40 -06:00
31e5f74e05 UI: misc: Replace spaces in Title with newlines when using custom title bar (since the Title is in an Avalonia tooltip) 2025-01-19 13:05:20 -06:00
f2f099bddb remove Async suffixes; they're factory methods not actual async methods. 2025-01-19 12:46:32 -06:00
2616dc57fb misc: chore: RelayCommand helper 2025-01-19 12:44:07 -06:00
0cdf7cfe21 UI: Open cheat manager in catch-all try 2025-01-18 22:48:06 -06:00
2ecf999569 misc: chore: change ThemeManager ThemeChanged to a basic Action since both arguments are unused 2025-01-18 22:48:06 -06:00
b612fc5155 Updated TitleIDs (#541)
Added more games to the RPC list. Now alphabetical.
2025-01-18 22:19:28 -06:00
25eb545409 Update bug_report.yml 2025-01-18 20:55:28 -06:00
52269964b6 Add the player select applet. (#537)
This introduces the somewhat completed version of the Player Select
Applet, allowing users to select either a user or a guest from the UI.
Note: Selecting the guest more then once currently does not work.

closes https://github.com/Ryubing/Ryujinx/issues/532
2025-01-18 20:40:33 -06:00
ccdddac8fc Fix compile warnings 2025-01-18 19:34:31 -06:00
1bc30bf3ba Update locales.json (#538)
Added a missing translation line
2025-01-18 18:40:51 -06:00
4868fface8 UI: Intel Mac warning
Upon launch, shows a warning about using an Intel Mac. This will only show once every boot. You can only turn it off by getting a better system.
2025-01-18 15:33:05 -06:00
6fca4492d0 misc: chore: Remove status update event stuff in Headless 2025-01-18 15:15:08 -06:00
ade2f256e0 misc: chore: remove duplicate graphics debug levels in headless windows 2025-01-18 11:19:38 -06:00
580b150c9a Revert "infra: Conditionally compile Metal & OpenGL depending on if the target RuntimeIdentifier is mac"
This reverts commit 2f93a0f706.
2025-01-18 10:57:02 -06:00
e6bad52945 Revert "Only selectively compile Metal & fix some compilation issues"
This reverts commit beda3206e0.
2025-01-18 10:56:58 -06:00
beda3206e0 Only selectively compile Metal & fix some compilation issues 2025-01-18 10:52:32 -06:00
2f93a0f706 infra: Conditionally compile Metal & OpenGL depending on if the target RuntimeIdentifier is mac 2025-01-18 10:38:29 -06:00
80f44d9547 misc: chore: small cleanup 2025-01-18 10:33:57 -06:00
b08e5db6d8 Headless: Dispose of inputmanager in a catch-all try 2025-01-18 10:30:19 -06:00
6a291d4116 Headless: Use main UI logo for window icon instead of separate bmp 2025-01-18 10:26:12 -06:00
6fc827fe67 headless: collapse headless window definition into a "Windows" folder, change GetWindowFlags to an abstract property. 2025-01-18 10:15:24 -06:00
6cd4866d76 Updated sv_SE in locales.json (#513) 2025-01-17 18:04:18 -06:00
4d7ca5c0f0 Update Chinese translations (#375) 2025-01-17 17:35:34 -06:00
a375faecc1 UI: Fix UpdateWaitWindow.axaml windows being too big on windows (#314) 2025-01-17 14:14:19 -06:00
1728b0f20c WWE 2K18 is not playable. 2025-01-17 11:37:08 -06:00
5aa071c59b remove notice for unusual core counts (#531) 2025-01-17 05:50:42 -06:00
1018c9db8b Update Norwegian Translation (#503)
Norwegian translation updated with the Compatibility list addition
2025-01-16 10:02:33 -06:00
01ccd18726 UI: Meant to use that method in another place [ci-skip] 2025-01-16 09:52:35 -06:00
abfbc6f4bc UI: Prevent desynced RPC when toggling it off/on while in-game 2025-01-16 09:52:01 -06:00
71 changed files with 1705 additions and 739 deletions

View File

@ -22,7 +22,7 @@ body:
id: log
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
description: "A log file will help our developers to better diagnose and fix the issue. UPLOAD THE FILE. DO NOT COPY AND PASTE THE FILE'S CONTENT."
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
validations:
required: true

View File

@ -202,7 +202,7 @@ jobs:
macos_release:
name: Release MacOS universal
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

View File

@ -183,7 +183,7 @@ jobs:
macos_release:
name: Release MacOS universal
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

View File

@ -19,7 +19,7 @@
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
<string>Copyright © 2018 - 2025 Ryujinx Team and Contributors.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>

View File

@ -167,7 +167,7 @@
01006C40086EA000,"AeternoBlade",nvdec,playable,2020-12-14 20:06:48
0100B1C00949A000,"AeternoBlade Demo",nvdec,playable,2021-02-09 14:39:26
01009D100EA28000,"AeternoBlade II",online-broken;UE4;vulkan-backend-bug,playable,2022-09-12 21:11:18
,"AeternoBlade II Demo Version",gpu;nvdec,ingame,2021-02-09 15:10:19
0100B1C00949A000,"AeternoBlade II Demo Version",gpu;nvdec,ingame,2021-02-09 15:10:19
01001B400D334000,"AFL Evolution 2",slow;online-broken;UE4,playable,2022-12-07 12:45:56
0100DB100BBCE000,"Afterparty",,playable,2022-09-22 12:23:19
010087C011C4E000,"Agatha Christie - The ABC Murders",,playable,2020-10-27 17:08:23
@ -477,7 +477,7 @@
010020700DE04000,"Bear With Me: The Lost Robots",nvdec,playable,2021-02-27 14:20:10
010024200E97E800,"Bear With Me: The Lost Robots Demo",nvdec,playable,2021-02-12 22:38:12
0100C0E014A4E000,"Bear's Restaurant",,playable,2024-08-11 21:26:59
,"BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~",crash,menus,2020-10-04 06:12:08
010045F00BF64000,"BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~",crash,menus,2020-10-04 06:12:08
01009C300BB4C000,"Beat Cop",,playable,2021-01-06 19:26:48
01002D20129FC000,"Beat Me!",online-broken,playable,2022-10-16 21:59:26
01006B0014590000,"BEAUTIFUL DESOLATION",gpu;nvdec,ingame,2022-10-26 10:34:38
@ -703,7 +703,7 @@
01006A30124CA000,"Chocobo GP",gpu;crash,ingame,2022-06-04 14:52:18
0100BF600BF26000,"Chocobo's Mystery Dungeon EVERY BUDDY!",slow,playable,2020-05-26 13:53:13
01000BA0132EA000,"Choices That Matter: And The Sun Went Out",,playable,2020-12-17 15:44:08
,"Chou no Doku Hana no Kusari: Taishou Irokoi Ibun",gpu;nvdec,ingame,2020-09-28 17:58:04
0100A1200CA3C000,"Chou no Doku Hana no Kusari: Taishou Irokoi Ibun",gpu;nvdec,ingame,2020-09-28 17:58:04
010039A008E76000,"ChromaGun",,playable,2020-05-26 12:56:42
010006800E13A000,"Chronos: Before the Ashes",UE4;gpu;nvdec,ingame,2020-12-11 22:16:35
010039700BA7E000,"Circle of Sumo",,playable,2020-05-22 12:45:21
@ -769,7 +769,7 @@
0100CCB01B1A0000,"COSMIC FANTASY COLLECTION",,ingame,2024-05-21 17:56:37
010067C00A776000,"Cosmic Star Heroine",,playable,2021-02-20 14:30:47
01003DD00F94A000,"COTTOn Reboot! [ コットン リブート! ]",,playable,2022-05-24 16:29:24
,"Cotton/Guardian Saturn Tribute Games",gpu,boots,2022-11-27 21:00:51
010077001526E000,"Cotton/Guardian Saturn Tribute Games",gpu,boots,2022-11-27 21:00:51
01000E301107A000,"Couch Co-Op Bundle Vol. 2",nvdec,playable,2022-10-02 12:04:21
0100C1E012A42000,"Country Tales",,playable,2021-06-17 16:45:39
01003370136EA000,"Cozy Grove",gpu,ingame,2023-07-30 22:22:19
@ -830,7 +830,7 @@
01003ED0099B0000,"Danger Mouse: The Danger Games",crash;online,boots,2022-07-22 15:49:45
0100EFA013E7C000,"Danger Scavenger",nvdec,playable,2021-04-17 15:53:04
0100417007F78000,"Danmaku Unlimited 3",,playable,2020-11-15 00:48:35
,"Darius Cozmic Collection",,playable,2021-02-19 20:59:06
01000330105BE000,"Darius Cozmic Collection",,playable,2021-02-19 20:59:06
010059C00BED4000,"Darius Cozmic Collection Special Edition",,playable,2022-07-22 16:26:50
010015800F93C000,"Dariusburst - Another Chronicle EX+",online,playable,2021-04-05 14:21:43
01003D301357A000,"Dark Arcana: The Carnival",gpu;slow,ingame,2022-02-19 08:52:28
@ -859,7 +859,7 @@
010095A011A14000,"Deadly Days",,playable,2020-11-27 13:38:55
0100BAC011928000,"Deadly Premonition 2: A Blessing In Disguise",,playable,2021-06-15 14:12:36
0100EBE00F22E000,"Deadly Premonition Origins",32-bit;nvdec,playable,2024-03-25 12:47:46
,"Dear Magi - Mahou Shounen Gakka -",,playable,2020-11-22 16:45:16
010015600D814000,"Dear Magi - Mahou Shounen Gakka -",,playable,2020-11-22 16:45:16
01000D60126B6000,"Death and Taxes",,playable,2020-12-15 20:27:49
010012B011AB2000,"Death Come True",nvdec,playable,2021-06-10 22:30:49
0100F3B00CF32000,"Death Coming",crash,nothing,2022-02-06 07:43:03
@ -902,13 +902,13 @@
010023600C704000,"Deponia",nvdec,playable,2021-01-26 17:17:19
0100ED700469A000,"Deru - The Art of Cooperation",,playable,2021-01-07 16:59:59
0100D4600D0E4000,"Descenders",gpu,ingame,2020-12-10 15:22:36
,"Desire remaster ver.",crash,boots,2021-01-17 02:34:37
0100D870102BC000,"Desire remaster ver.",crash,boots,2021-01-17 02:34:37
010069500DD86000,"Destiny Connect: Tick-Tock Travelers",UE4;gpu;nvdec,ingame,2020-12-16 12:20:36
01008BB011ED6000,"Destrobots",,playable,2021-03-06 14:37:05
01009E701356A000,"Destroy All Humans!",gpu;nvdec;UE4,ingame,2023-01-14 22:23:53
010030600E65A000,"Detective Dolittle",,playable,2021-03-02 14:03:59
01009C0009842000,"Detective Gallo",nvdec,playable,2022-07-24 11:51:04
,"Detective Jinguji Saburo Prism of Eyes",,playable,2020-10-02 21:54:41
01002D400B0F6000,"Detective Jinguji Saburo Prism of Eyes",,playable,2020-10-02 21:54:41
010007500F27C000,"Detective Pikachu™ Returns",,playable,2023-10-07 10:24:59
010031B00CF66000,"Devil Engine",,playable,2021-06-04 11:54:30
01002F000E8F2000,"Devil Kingdom",,playable,2023-01-31 08:58:44
@ -1057,7 +1057,7 @@
01004F000B716000,"Edna & Harvey: The Breakout Anniversary Edition",crash;nvdec,ingame,2022-08-01 16:59:56
01002550129F0000,"Effie",,playable,2022-10-27 14:36:39
0100CC0010A46000,"Ego Protocol: Remastered",nvdec,playable,2020-12-16 20:16:35
,"Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai",,playable,2020-11-12 00:11:50
01004CC00B352000,"Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai",,playable,2020-11-12 00:11:50
01003AD013BD2000,"Eight Dragons",nvdec,playable,2022-10-27 14:47:28
010020A01209C000,"El Hijo - A Wild West Tale",nvdec,playable,2021-04-19 17:44:08
0100B5B00EF38000,"Elden: Path of the Forgotten",,playable,2020-12-15 00:33:19
@ -1123,7 +1123,7 @@
01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29
010022700E7D6000,"FAR: Lone Sails",,playable,2022-09-06 16:33:05
0100C9E00FD62000,"Farabel",,playable,2020-08-03 17:47:28
,"Farm Expert 2019 for Nintendo Switch",,playable,2020-07-09 21:42:57
0100ECD00C806000,"Farm Expert 2019 for Nintendo Switch",,playable,2020-07-09 21:42:57
01000E400ED98000,"Farm Mystery",nvdec,playable,2022-09-06 16:46:47
010086B00BB50000,"Farm Together",,playable,2021-01-19 20:01:19
0100EB600E914000,"Farming Simulator 20",nvdec,playable,2021-06-13 10:52:44
@ -1246,12 +1246,12 @@
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
0100E1F013674000,"FUSER™",nvdec;UE4,playable,2022-10-17 20:58:32
,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
0100A7A015E4C000,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
01003C300B274000,"Futari de! Nyanko Daisensou",,playable,2024-01-05 22:26:52
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
0100EAD007E98000,"FUZE4 Nintendo Switch",vulkan-backend-bug,playable,2022-09-06 19:25:01
010067600F1A0000,"FuzzBall",crash,nothing,2021-03-29 20:13:21
,"G-MODE Archives 06 The strongest ever Julia Miyamoto",,playable,2020-10-15 13:06:26
0100275011e54000,"G-MODE Archives 06 The strongest ever Julia Miyamoto",,playable,2020-10-15 13:06:26
0100EB10108EA000,"G.I. Joe: Operation Blackout",UE4;crash,boots,2020-11-21 12:37:44
010048600B14E000,"Gal Metal",,playable,2022-07-27 20:57:48
010024700901A000,"Gal*Gun 2",nvdec;UE4,playable,2022-07-27 12:45:37
@ -1370,7 +1370,7 @@
01006F80082E4000,"GUILTY GEAR XX ACCENT CORE PLUS R",nvdec,playable,2021-01-13 09:28:33
01003C6008940000,"GUNBIRD for Nintendo Switch",32-bit,playable,2021-06-04 19:16:01
0100BCB00AE98000,"GUNBIRD2 for Nintendo Switch",,playable,2020-10-10 14:41:16
,"Gunka o haita neko",gpu;nvdec,ingame,2020-08-25 12:37:56
01003FF010312000,"Gunka o haita neko",gpu;nvdec,ingame,2020-08-25 12:37:56
010061000D318000,"Gunman Clive HD Collection",,playable,2020-10-09 12:17:35
01006D4003BCE000,"Guns, Gore and Cannoli 2",online,playable,2021-01-06 18:43:59
01008C800E654000,"Gunvolt Chronicles Luminous Avenger iX - Retail Version",,playable,2020-06-16 22:47:07
@ -1564,7 +1564,7 @@
0100BDC00A664000,"KAMEN RIDER CLIMAX SCRAMBLE",nvdec;ldn-untested,playable,2024-07-03 08:51:11
0100A9801180E000,"KAMEN RIDER memory of heroez / Premium Sound Edition",,playable,2022-12-06 03:14:26
010085300314E000,"KAMIKO",,playable,2020-05-13 12:48:57
,"Kangokuto Mary Skelter Finale",audio;crash,ingame,2021-01-09 22:39:28
010042C011736000,"Kangokuto Mary Skelter Finale",audio;crash,ingame,2021-01-09 22:39:28
01007FD00DB20000,"Katakoi Contrast - collection of branch -",nvdec,playable,2022-12-09 09:41:26
0100D7000C2C6000,"Katamari Damacy REROLL",,playable,2022-08-02 21:35:05
0100F9800EDFA000,"KATANA KAMI: A Way of the Samurai Story",slow,playable,2022-04-09 10:40:16
@ -1581,7 +1581,7 @@
0100FB400D832000,"KILL la KILL -IF",,playable,2020-06-09 14:47:08
010011B00910C000,"Kill The Bad Guy",,playable,2020-05-12 22:16:10
0100F2900B3E2000,"Killer Queen Black",ldn-untested;online,playable,2021-04-08 12:46:18
,"Kin'iro no Corda Octave",,playable,2020-09-22 13:23:12
010014A00C5E0000,"Kin'iro no Corda Octave",,playable,2020-09-22 13:23:12
010089000F0E8000,"Kine",UE4,playable,2022-09-14 14:28:37
0100E6B00FFBA000,"King Lucas",,playable,2022-09-21 19:43:23
0100B1300783E000,"King Oddball",,playable,2020-05-13 13:47:57
@ -1612,7 +1612,7 @@
01009EF00DDB4000,"Knockout City™",services;online-broken,boots,2022-12-09 09:48:58
0100C57019BA2000,"Koa and the Five Pirates of Mara",gpu,ingame,2024-07-11 16:14:44
01001E500401C000,"Koi DX",,playable,2020-05-11 21:37:51
,"Koi no Hanasaku Hyakkaen",32-bit;gpu;nvdec,ingame,2020-10-03 14:17:10
010052300F612000,"Koi no Hanasaku Hyakkaen",32-bit;gpu;nvdec,ingame,2020-10-03 14:17:10
01005D200C9AA000,"Koloro",,playable,2022-08-03 12:34:02
0100464009294000,"Kona",,playable,2022-08-03 12:48:19
010016C011AAA000,"Kono Subarashii Sekai ni Shukufuku o Kono Yokubo no Isho ni Choai o",,playable,2023-04-26 09:51:08
@ -1779,8 +1779,8 @@
0100EC000CE24000,"Mech Rage",,playable,2020-11-18 12:30:16
0100C4F005EB4000,"Mecho Tales",,playable,2022-08-04 17:03:19
0100E4600D31A000,"Mechstermination Force",,playable,2024-07-04 05:39:15
,"Medarot Classics Plus Kabuto Ver",,playable,2020-11-21 11:31:18
,"Medarot Classics Plus Kuwagata Ver",,playable,2020-11-21 11:30:40
01007580124C0000,"Medarot Classics Plus Kabuto Ver",,playable,2020-11-21 11:31:18
0100228012682000,"Medarot Classics Plus Kuwagata Ver",,playable,2020-11-21 11:30:40
0100BBC00CB9A000,"Mega Mall Story",slow,playable,2022-08-04 17:10:58
0100B0C0086B0000,"Mega Man 11",,playable,2021-04-26 12:07:53
010038E016264000,"Mega Man Battle Network Legacy Collection Vol. 1",,playable,2023-04-25 03:55:57
@ -1797,7 +1797,7 @@
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
010062F011E7C000,"Memory Lane",UE4,playable,2022-10-05 14:31:03
0100EBE00D5B0000,"Meow Motors",UE4;gpu,ingame,2020-12-18 00:24:01
0100273008FBC000,"Mercenaries Saga Chronicles",,playable,2021-01-10 12:48:19
@ -1873,7 +1873,7 @@
010093A01305C000,"Monster Hunter Rise Demo",online-broken;ldn-works;demo,playable,2022-10-18 23:04:17
0100E21011446000,"Monster Hunter Stories 2: Wings of Ruin",services,ingame,2022-07-10 19:27:30
010042501329E000,"MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version",demo,playable,2022-11-13 22:20:26
,"Monster Hunter XX Demo",32-bit;cpu,nothing,2020-03-22 10:12:28
0100C51003B46000,"Monster Hunter XX Demo",32-bit;cpu,nothing,2020-03-22 10:12:28
0100C3800049C000,"Monster Hunter XX Nintendo Switch Ver ( Double Cross )",,playable,2024-07-21 14:08:09
010088400366E000,"Monster Jam Crush It!",UE4;nvdec;online,playable,2021-04-08 19:29:27
010095C00F354000,"Monster Jam Steel Titans",crash;nvdec;UE4,menus,2021-11-14 09:45:38
@ -1917,7 +1917,7 @@
010035901046C000,"Mushroom Quest",,playable,2020-05-17 13:07:08
0100700006EF6000,"Mushroom Wars 2",nvdec,playable,2020-09-28 15:26:08
010046400F310000,"Music Racer",,playable,2020-08-10 08:51:23
,"Musou Orochi 2 Ultimate",crash;nvdec,boots,2021-04-09 19:39:16
0100153006300000,"Musou Orochi 2 Ultimate",crash;nvdec,boots,2021-04-09 19:39:16
0100F6000EAA8000,"Must Dash Amigos",,playable,2022-09-20 16:45:56
01007B6006092000,"MUSYNX",,playable,2020-05-08 14:24:43
0100C3E00ACAA000,"Mutant Football League: Dynasty Edition",online-broken,playable,2022-08-05 17:01:51
@ -1948,7 +1948,7 @@
0100A6F00AC70000,"NAIRI: Tower of Shirin",nvdec,playable,2020-08-09 19:49:12
010002F001220000,"NAMCO MUSEUM",ldn-untested,playable,2024-08-13 07:52:21
0100DAA00AEE6000,"NAMCO MUSEUM™ ARCADE PAC™",,playable,2021-06-07 21:44:50
,"NAMCOT COLLECTION",audio,playable,2020-06-25 13:35:22
010039F010E14000,"NAMCOT COLLECTION",audio,playable,2020-06-25 13:35:22
010072B00BDDE000,"Narcos: Rise of the Cartels",UE4;crash;nvdec,boots,2021-03-22 13:18:47
01006BB00800A000,"NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst",nvdec,playable,2024-06-16 14:58:05
010084D00CF5E000,"NARUTO SHIPPUDEN™: Ultimate Ninja® STORM 4 ROAD TO BORUTO",,playable,2024-06-29 13:04:22
@ -2089,11 +2089,11 @@
0100F9D00C186000,"Olympia Soiree",,playable,2022-12-04 21:07:12
0100A8B00E14A000,"Olympic Games Tokyo 2020 The Official Video Game™",ldn-untested;nvdec;online,playable,2021-01-06 01:20:24
01001D600E51A000,"Omega Labyrinth Life",,playable,2021-02-23 21:03:03
,"Omega Vampire",nvdec,playable,2020-10-17 19:15:35
01005DE00CA34000,"Omega Vampire",nvdec,playable,2020-10-17 19:15:35
0100CDC00C40A000,"Omensight: Definitive Edition",UE4;crash;nvdec,ingame,2020-07-26 01:45:14
01006DB00D970000,"OMG Zombies!",32-bit,playable,2021-04-12 18:04:45
010014E017B14000,"OMORI",,playable,2023-01-07 20:21:02
,"Once Upon A Coma",nvdec,playable,2020-08-01 12:09:39
0100A5F011800000,"Once Upon A Coma",nvdec,playable,2020-08-01 12:09:39
0100BD3006A02000,"One More Dungeon",,playable,2021-01-06 09:10:58
010076600FD64000,"One Person Story",,playable,2020-07-14 11:51:02
0100774009CF6000,"ONE PIECE Pirate Warriors 3 Deluxe Edition",nvdec,playable,2020-05-10 06:23:52
@ -2184,7 +2184,7 @@
010062B01525C000,"Persona 4 Golden",,playable,2024-08-07 17:48:07
01005CA01580E000,"Persona 5 Royal",gpu,ingame,2024-08-17 21:45:15
010087701B092000,"Persona 5 Tactica",,playable,2024-04-01 22:21:03
,"Persona 5: Scramble",deadlock,boots,2020-10-04 03:22:29
0100E4F010D92000,"Persona 5: Scramble",deadlock,boots,2020-10-04 03:22:29
0100801011C3E000,"Persona® 5 Strikers",nvdec;mac-bug,playable,2023-09-26 09:36:01
010044400EEAE000,"Petoons Party",nvdec,playable,2021-03-02 21:07:58
010053401147C000,"PGA TOUR 2K21",deadlock;nvdec,ingame,2022-10-05 21:53:50
@ -2273,7 +2273,7 @@
0100D1C01C194000,"Powerful Pro Baseball 2024-2025",gpu,ingame,2024-08-25 06:40:48
01008E100E416000,"PowerSlave Exhumed",gpu,ingame,2023-07-31 23:19:10
010054F01266C000,"Prehistoric Dude",gpu,ingame,2020-10-12 12:38:48
,"Pretty Princess Magical Coordinate",,playable,2020-10-15 11:43:41
0100DB200D3E4000,"Pretty Princess Magical Coordinate",,playable,2020-10-15 11:43:41
01007F00128CC000,"Pretty Princess Party",,playable,2022-10-19 17:23:58
010009300D278000,"Preventive Strike",nvdec,playable,2022-10-06 10:55:51
0100210019428000,"Prince of Persia The Lost Crown",crash,ingame,2024-06-08 21:31:58
@ -2294,13 +2294,13 @@
0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43
01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27
0100BDB01150E000,"Project Warlock",,playable,2020-06-16 10:50:41
,"Psikyo Collection Vol 1",32-bit,playable,2020-10-11 13:18:47
01009F100BC52000,"Psikyo Collection Vol 1",32-bit,playable,2020-10-11 13:18:47
0100A2300DB78000,"Psikyo Collection Vol. 3",,ingame,2021-06-07 02:46:23
01009D400C4A8000,"Psikyo Collection Vol.2",32-bit,playable,2021-06-07 03:22:07
01007A200F2E2000,"Psikyo Shooting Stars Alpha",32-bit,playable,2021-04-13 12:03:43
0100D7400F2E4000,"Psikyo Shooting Stars Bravo",32-bit,playable,2021-06-14 12:09:07
0100EC100A790000,"PSYVARIAR DELTA",nvdec,playable,2021-01-20 13:01:46
,"Puchitto kurasutā",Need-Update;crash;services,menus,2020-07-04 16:44:28
0100AE700F184000,"Puchitto kurasutā",Need-Update;crash;services,menus,2020-07-04 16:44:28
0100D61010526000,"Pulstario",,playable,2022-10-06 11:02:01
01009AE00B788000,"Pumped BMX Pro",nvdec;online-broken,playable,2022-09-20 17:40:50
01006C10131F6000,"Pumpkin Jack",nvdec;UE4,playable,2022-10-13 12:52:32
@ -2325,7 +2325,7 @@
0100DCF00F13A000,"Queen's Quest 4: Sacred Truce",nvdec,playable,2022-10-13 12:59:21
0100492012378000,"Quell",gpu,ingame,2021-06-11 15:59:53
01001DE005012000,"Quest of Dungeons",,playable,2021-06-07 10:29:22
,"QuietMansion2",,playable,2020-09-03 14:59:35
010067D011E68000,"QuietMansion2",,playable,2020-09-03 14:59:35
0100AF100EE76000,"Quiplash 2 InterLASHional: The Say Anything Party Game!",online-working,playable,2022-10-19 17:43:45
0100E5400BE64000,"R-Type Dimensions EX",,playable,2020-10-09 12:04:43
0100F930136B6000,"R-Type® Final 2",slow;nvdec;UE4,ingame,2022-10-30 21:46:29
@ -2383,7 +2383,7 @@
01007A800D520000,"Refunct",UE4,playable,2020-12-15 22:46:21
0100FDF0083A6000,"Regalia: Of Men and Monarchs - Royal Edition",,playable,2022-08-11 12:24:01
01005FD00F15A000,"Regions of Ruin",,playable,2020-08-05 11:38:58
,"Reine des Fleurs",cpu;crash,boots,2020-09-27 18:50:39
0100B5800C0E4000,"Reine des Fleurs",cpu;crash,boots,2020-09-27 18:50:39
0100F1900B144000,"REKT! High Octane Stunts",online,playable,2020-09-28 12:33:56
01002AD013C52000,"Relicta",nvdec;UE4,playable,2022-10-31 12:48:33
010095900B436000,"RemiLore",,playable,2021-06-03 18:58:15
@ -2495,7 +2495,7 @@
01002DF00F76C000,"SAMURAI SHODOWN",UE4;crash;nvdec,menus,2020-09-06 02:17:00
0100F6800F48E000,"SAMURAI SHODOWN NEOGEO COLLECTION",nvdec,playable,2021-06-14 17:12:56
0100B6501A360000,"Samurai Warrior",,playable,2023-02-27 18:42:38
,"Sangoku Rensenki ~Otome no Heihou!~",gpu;nvdec,ingame,2020-10-17 19:13:14
01000EA00B23C000,"Sangoku Rensenki ~Otome no Heihou!~",gpu;nvdec,ingame,2020-10-17 19:13:14
0100A4700BC98000,"Satsujin Tantei Jack the Ripper",,playable,2021-06-21 16:32:54
0100F0000869C000,"Saturday Morning RPG",nvdec,playable,2022-08-12 12:41:50
01006EE00380C000,"Sausage Sports Club",gpu,ingame,2021-01-10 05:37:17
@ -2532,7 +2532,7 @@
010054400D2E6000,"SEGA AGES Virtua Racing",online-broken,playable,2023-01-29 17:08:39
01001E700AC60000,"SEGA AGES Wonder Boy: Monster Land",online,playable,2021-05-05 16:28:25
0100B3C014BDA000,"SEGA Genesis™ Nintendo Switch Online",crash;regression,nothing,2022-04-11 07:27:21
,"SEGA Mega Drive Classics",online,playable,2021-01-05 11:08:00
0100F7300B24E000,"SEGA Mega Drive Classics",online,playable,2021-01-05 11:08:00
01009840046BC000,"Semispheres",,playable,2021-01-06 23:08:31
0100D1800D902000,"SENRAN KAGURA Peach Ball",,playable,2021-06-03 15:12:10
0100E0C00ADAC000,"SENRAN KAGURA Reflexions",,playable,2020-03-23 19:15:23
@ -2585,7 +2585,7 @@
0100B2E00F13E000,"Shipped",,playable,2020-11-21 14:22:32
01000E800FCB4000,"Ships",,playable,2021-06-11 16:14:37
01007430122D0000,"Shiren the Wanderer: The Tower of Fortune and the Dice of Fate",nvdec,playable,2022-10-20 11:44:36
,"Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~",cpu;crash,boots,2020-09-27 19:01:25
010027300A660000,"Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~",cpu;crash,boots,2020-09-27 19:01:25
01000244016BAE00,"Shiro0",gpu,ingame,2024-01-13 08:54:39
0100CCE00DDB6000,"Shoot 1UP DX",,playable,2020-12-13 12:32:47
01001180021FA000,"Shovel Knight: Specter of Torment",,playable,2020-05-30 08:34:17
@ -2626,7 +2626,7 @@
0100C52011460000,"Sky: Children of the Light",cpu;online-broken,nothing,2023-02-23 10:57:10
010041C01014E000,"Skybolt Zack",,playable,2021-04-12 18:28:00
0100A0A00D1AA000,"SKYHILL",,playable,2021-03-05 15:19:11
,"Skylanders Imaginators",crash;services,boots,2020-05-30 18:49:18
0100CCC0002E6000,"Skylanders Imaginators",crash;services,boots,2020-05-30 18:49:18
010021A00ABEE000,"SKYPEACE",,playable,2020-05-29 14:14:30
0100EA400BF44000,"SkyScrappers",,playable,2020-05-28 22:11:25
0100F3C00C400000,"SkyTime",slow,ingame,2020-05-30 09:24:51
@ -2681,7 +2681,7 @@
01005EA01C0FC000,"SONIC X SHADOW GENERATIONS",crash,ingame,2025-01-07 04:20:45
010064F00C212000,"Soul Axiom Rebooted",nvdec;slow,ingame,2020-09-04 12:41:01
0100F2100F0B2000,"Soul Searching",,playable,2020-07-09 18:39:07
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken,playable,2024-07-08 17:47:28
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken;vulkan-backend-bug;gpu,ingame,2025-01-21 17:35:10
0100B9F00C162000,"Space Blaze",,playable,2020-08-30 16:18:05
010005500E81E000,"Space Cows",UE4;crash,menus,2020-06-15 11:33:20
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
@ -2797,7 +2797,7 @@
0100681011B56000,"Struggling",,playable,2020-10-15 20:37:03
0100AF000B4AE000,"Stunt Kite Party",nvdec,playable,2021-01-25 17:16:56
0100C5500E7AE000,"STURMWIND EX",audio;32-bit,playable,2022-09-16 12:01:39
,"Subarashiki Kono Sekai -Final Remix-",services;slow,ingame,2020-02-10 16:21:51
01001C1009892000,"Subarashiki Kono Sekai -Final Remix-",services;slow,ingame,2020-02-10 16:21:51
010001400E474000,"Subdivision Infinity DX",UE4;crash,boots,2021-03-03 14:26:46
0100E6400BCE8000,"Sublevel Zero Redux",,playable,2022-09-16 12:30:03
0100EDA00D866000,"Submerged",nvdec;UE4;vulkan-backend-bug,playable,2022-08-16 15:17:01
@ -2846,9 +2846,9 @@
0100284007D6C000,"Super One More Jump",,playable,2022-08-17 16:47:47
01001F90122B2000,"Super Punch Patrol",,playable,2024-07-12 19:49:02
0100331005E8E000,"Super Putty Squad",gpu;32-bit,ingame,2024-04-29 15:51:54
,"SUPER ROBOT WARS T",online,playable,2021-03-25 11:00:40
,"SUPER ROBOT WARS V",online,playable,2020-06-23 12:56:37
,"SUPER ROBOT WARS X",online,playable,2020-08-05 19:18:51
01006C900CC60000,"SUPER ROBOT WARS T",online,playable,2021-03-25 11:00:40
0100CA400E300000,"SUPER ROBOT WARS V",online,playable,2020-06-23 12:56:37
010026800E304000,"SUPER ROBOT WARS X",online,playable,2020-08-05 19:18:51
01004CF00A60E000,"Super Saurio Fly",nvdec,playable,2020-08-06 13:12:14
010039700D200000,"Super Skelemania",,playable,2020-06-07 22:59:50
01006A800016E000,"Super Smash Bros.™ Ultimate",gpu;crash;nvdec;ldn-works;intel-vendor-bug,ingame,2024-09-14 23:05:21
@ -3014,7 +3014,7 @@
010085A00C5E8000,"The Lord of the Rings: Adventure Card Game - Definitive Edition",online-broken,menus,2022-09-16 15:19:32
01008A000A404000,"The Lost Child",nvdec,playable,2021-02-23 15:44:20
0100BAB00A116000,"The Low Road",,playable,2021-02-26 13:23:22
,"The Mahjong",Needs Update;crash;services,nothing,2021-04-01 22:06:22
01005F3006AFE000,"The Mahjong",Needs Update;crash;services,nothing,2021-04-01 22:06:22
0100DC300AC78000,"The Messenger",,playable,2020-03-22 13:51:37
0100DEC00B2BC000,"The Midnight Sanctuary",nvdec;UE4;vulkan-backend-bug,playable,2022-10-03 17:17:32
0100F1B00B456000,"The MISSING: J.J. Macfield and the Island of Memories",,playable,2022-08-22 19:36:18
@ -3060,7 +3060,7 @@
010064E00ECBC000,"The Unicorn Princess",,playable,2022-09-16 16:20:56
0100BCF00E970000,"The Vanishing of Ethan Carter",UE4,playable,2021-06-09 17:14:47
0100D0500B0A6000,"The VideoKid",nvdec,playable,2021-01-06 09:28:24
,"The Voice",services,menus,2020-07-28 20:48:49
01008CF00BA38000,"The Voice",services,menus,2020-07-28 20:48:49
010056E00B4F4000,"The Walking Dead: A New Frontier",,playable,2022-09-21 13:40:48
010099100B6AC000,"The Walking Dead: Season Two",,playable,2020-08-09 12:57:06
010029200B6AA000,"The Walking Dead: The Complete First Season",,playable,2021-06-04 13:10:56
@ -3348,7 +3348,7 @@
01001C400482C000,"Wunderling DX",audio;crash,ingame,2022-09-10 13:20:12
01003B401148E000,"Wurroom",,playable,2020-10-07 22:46:21
010081700EDF4000,"WWE 2K Battlegrounds",nvdec;online-broken;UE4,playable,2022-10-07 12:44:40
010009800203E000,"WWE 2K18",nvdec,playable,2023-10-21 17:22:01
010009800203E000,"WWE 2K18",nvdec;online-broken,ingame,2025-01-17 11:36:56
0100DF100B97C000,"X-Morph: Defense",,playable,2020-06-22 11:05:31
0100D0B00FB74000,"XCOM® 2 Collection",gpu;crash,ingame,2022-10-04 09:38:30
0100CC9015360000,"XEL",gpu,ingame,2022-10-03 10:19:39
@ -3376,7 +3376,7 @@
010022F00DA66000,"Yooka-Laylee and the Impossible Lair",,playable,2021-03-05 17:32:21
01006000040C2000,"Yoshis Crafted World™",gpu;audout,ingame,2021-08-30 13:25:51
0100AE800C9C6000,"Yoshis Crafted World™ Demo",gpu,boots,2020-12-16 14:57:40
,"Yoshiwara Higanbana Kuon no Chigiri",nvdec,playable,2020-10-17 19:14:46
0100BBA00B23E000,"Yoshiwara Higanbana Kuon no Chigiri",nvdec,playable,2020-10-17 19:14:46
01003A400C3DA800,"YouTube",,playable,2024-06-08 05:24:10
00100A7700CCAA40,"Youtubers Life00",nvdec,playable,2022-09-03 14:56:19
0100E390124D8000,"Ys IX: Monstrum Nox",,playable,2022-06-12 04:14:42
@ -3386,7 +3386,7 @@
01002D60188DE000,"Yu-Gi-Oh! Rush Duel: Dawn of the Battle Royale!! Let's Go! Go Rush!!",crash,ingame,2023-03-17 01:54:01
010037D00DBDC000,"YU-NO: A girl who chants love at the bound of this world.",nvdec,playable,2021-01-26 17:03:52
0100B56011502000,"Yumeutsutsu Re:After",,playable,2022-11-20 16:09:06
,"Yunohana Spring! - Mellow Times -",audio;crash,menus,2020-09-27 19:27:40
0100DE200C0DA000,"Yunohana Spring! - Mellow Times -",audio;crash,menus,2020-09-27 19:27:40
0100307011C44000,"Yuppie Psycho: Executive Edition",crash,ingame,2020-12-11 10:37:06
0100FC900963E000,"Yuri",,playable,2021-06-11 13:08:50
010092400A678000,"Zaccaria Pinball",online-broken,playable,2022-09-03 15:44:28
@ -3397,7 +3397,7 @@
0100AAC00E692000,"Zenith",,playable,2022-09-17 09:57:02
0100A6A00894C000,"ZERO GUNNER 2- for Nintendo Switch",,playable,2021-01-04 20:17:14
01004B001058C000,"Zero Strain",services;UE4,menus,2021-11-10 07:48:32
,"Zettai kaikyu gakuen",gpu;nvdec,ingame,2020-08-25 15:15:54
010021300F69E000,"Zettai kaikyu gakuen",gpu;nvdec,ingame,2020-08-25 15:15:54
0100D7B013DD0000,"Ziggy the Chaser",,playable,2021-02-04 20:34:27
010086700EF16000,"ZikSquare",gpu,ingame,2021-11-06 02:02:48
010069C0123D8000,"Zoids Wild Blast Unleashed",nvdec,playable,2022-10-15 11:26:59
@ -3409,7 +3409,7 @@
0100CD300A1BA000,"Zombillie",,playable,2020-07-23 17:42:23
01001EE00A6B0000,"Zotrix: Solar Division",,playable,2021-06-07 20:34:05
0100B9B00C6A4000,"この世の果てで恋を唄う少女YU-NO",audio,ingame,2021-01-22 07:00:16
,"スーパーファミコン Nintendo Switch Online",slow,ingame,2020-03-14 05:48:38
0100E8600C504000,"スーパーファミコン Nintendo Switch Online",slow,ingame,2020-03-14 05:48:38
01000BB01CB8A000,"トラブル・マギア ~訳アリ少女は未来を勝ち取るために異国の魔法学校へ留学します~(Trouble Magia ~Wakeari Shoujo wa Mirai o Kachitoru Tame ni Ikoku no Mahou Gakkou e Ryuugaku Shimasu~)",,nothing,2024-09-28 07:03:14
010065500B218000,"メモリーズオフ - Innocent Fille",,playable,2022-12-02 17:36:48
010032400E700000,"二ノ国 白き聖灰の女王",services;32-bit,menus,2023-04-16 17:11:06
@ -3421,4 +3421,4 @@
0100936018EB4000,"牧場物語 Welcomeワンダフルライフ",crash,ingame,2023-04-25 19:43:52
0100F4401940A000,"超探偵事件簿 レインコード (Master Detective Archives: Rain Code)",crash,ingame,2024-02-12 20:58:31
010064801A01C000,"超次元ゲイム ネプテューヌ GameMaker R:Evolution",crash,nothing,2023-10-30 22:37:40
0100F3400332C000,"ブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
0100F3400332C000,"ブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41

1 title_id game_name labels status last_updated
167 01006C40086EA000 AeternoBlade nvdec playable 2020-12-14 20:06:48
168 0100B1C00949A000 AeternoBlade Demo nvdec playable 2021-02-09 14:39:26
169 01009D100EA28000 AeternoBlade II online-broken;UE4;vulkan-backend-bug playable 2022-09-12 21:11:18
170 0100B1C00949A000 AeternoBlade II Demo Version gpu;nvdec ingame 2021-02-09 15:10:19
171 01001B400D334000 AFL Evolution 2 slow;online-broken;UE4 playable 2022-12-07 12:45:56
172 0100DB100BBCE000 Afterparty playable 2022-09-22 12:23:19
173 010087C011C4E000 Agatha Christie - The ABC Murders playable 2020-10-27 17:08:23
477 010020700DE04000 Bear With Me: The Lost Robots nvdec playable 2021-02-27 14:20:10
478 010024200E97E800 Bear With Me: The Lost Robots Demo nvdec playable 2021-02-12 22:38:12
479 0100C0E014A4E000 Bear's Restaurant playable 2024-08-11 21:26:59
480 010045F00BF64000 BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~ crash menus 2020-10-04 06:12:08
481 01009C300BB4C000 Beat Cop playable 2021-01-06 19:26:48
482 01002D20129FC000 Beat Me! online-broken playable 2022-10-16 21:59:26
483 01006B0014590000 BEAUTIFUL DESOLATION gpu;nvdec ingame 2022-10-26 10:34:38
703 01006A30124CA000 Chocobo GP gpu;crash ingame 2022-06-04 14:52:18
704 0100BF600BF26000 Chocobo's Mystery Dungeon EVERY BUDDY! slow playable 2020-05-26 13:53:13
705 01000BA0132EA000 Choices That Matter: And The Sun Went Out playable 2020-12-17 15:44:08
706 0100A1200CA3C000 Chou no Doku Hana no Kusari: Taishou Irokoi Ibun gpu;nvdec ingame 2020-09-28 17:58:04
707 010039A008E76000 ChromaGun playable 2020-05-26 12:56:42
708 010006800E13A000 Chronos: Before the Ashes UE4;gpu;nvdec ingame 2020-12-11 22:16:35
709 010039700BA7E000 Circle of Sumo playable 2020-05-22 12:45:21
769 0100CCB01B1A0000 COSMIC FANTASY COLLECTION ingame 2024-05-21 17:56:37
770 010067C00A776000 Cosmic Star Heroine playable 2021-02-20 14:30:47
771 01003DD00F94A000 COTTOn Reboot! [ コットン リブート! ] playable 2022-05-24 16:29:24
772 010077001526E000 Cotton/Guardian Saturn Tribute Games gpu boots 2022-11-27 21:00:51
773 01000E301107A000 Couch Co-Op Bundle Vol. 2 nvdec playable 2022-10-02 12:04:21
774 0100C1E012A42000 Country Tales playable 2021-06-17 16:45:39
775 01003370136EA000 Cozy Grove gpu ingame 2023-07-30 22:22:19
830 01003ED0099B0000 Danger Mouse: The Danger Games crash;online boots 2022-07-22 15:49:45
831 0100EFA013E7C000 Danger Scavenger nvdec playable 2021-04-17 15:53:04
832 0100417007F78000 Danmaku Unlimited 3 playable 2020-11-15 00:48:35
833 01000330105BE000 Darius Cozmic Collection playable 2021-02-19 20:59:06
834 010059C00BED4000 Darius Cozmic Collection Special Edition playable 2022-07-22 16:26:50
835 010015800F93C000 Dariusburst - Another Chronicle EX+ online playable 2021-04-05 14:21:43
836 01003D301357A000 Dark Arcana: The Carnival gpu;slow ingame 2022-02-19 08:52:28
859 010095A011A14000 Deadly Days playable 2020-11-27 13:38:55
860 0100BAC011928000 Deadly Premonition 2: A Blessing In Disguise playable 2021-06-15 14:12:36
861 0100EBE00F22E000 Deadly Premonition Origins 32-bit;nvdec playable 2024-03-25 12:47:46
862 010015600D814000 Dear Magi - Mahou Shounen Gakka - playable 2020-11-22 16:45:16
863 01000D60126B6000 Death and Taxes playable 2020-12-15 20:27:49
864 010012B011AB2000 Death Come True nvdec playable 2021-06-10 22:30:49
865 0100F3B00CF32000 Death Coming crash nothing 2022-02-06 07:43:03
902 010023600C704000 Deponia nvdec playable 2021-01-26 17:17:19
903 0100ED700469A000 Deru - The Art of Cooperation playable 2021-01-07 16:59:59
904 0100D4600D0E4000 Descenders gpu ingame 2020-12-10 15:22:36
905 0100D870102BC000 Desire remaster ver. crash boots 2021-01-17 02:34:37
906 010069500DD86000 Destiny Connect: Tick-Tock Travelers UE4;gpu;nvdec ingame 2020-12-16 12:20:36
907 01008BB011ED6000 Destrobots playable 2021-03-06 14:37:05
908 01009E701356A000 Destroy All Humans! gpu;nvdec;UE4 ingame 2023-01-14 22:23:53
909 010030600E65A000 Detective Dolittle playable 2021-03-02 14:03:59
910 01009C0009842000 Detective Gallo nvdec playable 2022-07-24 11:51:04
911 01002D400B0F6000 Detective Jinguji Saburo Prism of Eyes playable 2020-10-02 21:54:41
912 010007500F27C000 Detective Pikachu™ Returns playable 2023-10-07 10:24:59
913 010031B00CF66000 Devil Engine playable 2021-06-04 11:54:30
914 01002F000E8F2000 Devil Kingdom playable 2023-01-31 08:58:44
1057 01004F000B716000 Edna & Harvey: The Breakout – Anniversary Edition crash;nvdec ingame 2022-08-01 16:59:56
1058 01002550129F0000 Effie playable 2022-10-27 14:36:39
1059 0100CC0010A46000 Ego Protocol: Remastered nvdec playable 2020-12-16 20:16:35
1060 01004CC00B352000 Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai playable 2020-11-12 00:11:50
1061 01003AD013BD2000 Eight Dragons nvdec playable 2022-10-27 14:47:28
1062 010020A01209C000 El Hijo - A Wild West Tale nvdec playable 2021-04-19 17:44:08
1063 0100B5B00EF38000 Elden: Path of the Forgotten playable 2020-12-15 00:33:19
1123 01005C10136CA000 Fantasy Tavern Sextet -Vol.2 Adventurer's Days- gpu;slow;crash ingame 2021-11-06 02:57:29
1124 010022700E7D6000 FAR: Lone Sails playable 2022-09-06 16:33:05
1125 0100C9E00FD62000 Farabel playable 2020-08-03 17:47:28
1126 0100ECD00C806000 Farm Expert 2019 for Nintendo Switch playable 2020-07-09 21:42:57
1127 01000E400ED98000 Farm Mystery nvdec playable 2022-09-06 16:46:47
1128 010086B00BB50000 Farm Together playable 2021-01-19 20:01:19
1129 0100EB600E914000 Farming Simulator 20 nvdec playable 2021-06-13 10:52:44
1246 0100ECE00C0C4000 Fury Unleashed crash;services ingame 2020-10-18 11:52:40
1247 010070000ED9E000 Fury Unleashed Demo playable 2020-10-08 20:09:21
1248 0100E1F013674000 FUSER™ nvdec;UE4 playable 2022-10-17 20:58:32
1249 0100A7A015E4C000 Fushigi no Gensokyo Lotus Labyrinth Needs Update;audio;gpu;nvdec ingame 2021-01-20 15:30:02
1250 01003C300B274000 Futari de! Nyanko Daisensou playable 2024-01-05 22:26:52
1251 010055801134E000 FUZE Player online-broken;vulkan-backend-bug ingame 2022-10-18 12:23:53
1252 0100EAD007E98000 FUZE4 Nintendo Switch vulkan-backend-bug playable 2022-09-06 19:25:01
1253 010067600F1A0000 FuzzBall crash nothing 2021-03-29 20:13:21
1254 0100275011e54000 G-MODE Archives 06 The strongest ever Julia Miyamoto playable 2020-10-15 13:06:26
1255 0100EB10108EA000 G.I. Joe: Operation Blackout UE4;crash boots 2020-11-21 12:37:44
1256 010048600B14E000 Gal Metal playable 2022-07-27 20:57:48
1257 010024700901A000 Gal*Gun 2 nvdec;UE4 playable 2022-07-27 12:45:37
1370 01006F80082E4000 GUILTY GEAR XX ACCENT CORE PLUS R nvdec playable 2021-01-13 09:28:33
1371 01003C6008940000 GUNBIRD for Nintendo Switch 32-bit playable 2021-06-04 19:16:01
1372 0100BCB00AE98000 GUNBIRD2 for Nintendo Switch playable 2020-10-10 14:41:16
1373 01003FF010312000 Gunka o haita neko gpu;nvdec ingame 2020-08-25 12:37:56
1374 010061000D318000 Gunman Clive HD Collection playable 2020-10-09 12:17:35
1375 01006D4003BCE000 Guns, Gore and Cannoli 2 online playable 2021-01-06 18:43:59
1376 01008C800E654000 Gunvolt Chronicles Luminous Avenger iX - Retail Version playable 2020-06-16 22:47:07
1564 0100BDC00A664000 KAMEN RIDER CLIMAX SCRAMBLE nvdec;ldn-untested playable 2024-07-03 08:51:11
1565 0100A9801180E000 KAMEN RIDER memory of heroez / Premium Sound Edition playable 2022-12-06 03:14:26
1566 010085300314E000 KAMIKO playable 2020-05-13 12:48:57
1567 010042C011736000 Kangokuto Mary Skelter Finale audio;crash ingame 2021-01-09 22:39:28
1568 01007FD00DB20000 Katakoi Contrast - collection of branch - nvdec playable 2022-12-09 09:41:26
1569 0100D7000C2C6000 Katamari Damacy REROLL playable 2022-08-02 21:35:05
1570 0100F9800EDFA000 KATANA KAMI: A Way of the Samurai Story slow playable 2022-04-09 10:40:16
1581 0100FB400D832000 KILL la KILL -IF playable 2020-06-09 14:47:08
1582 010011B00910C000 Kill The Bad Guy playable 2020-05-12 22:16:10
1583 0100F2900B3E2000 Killer Queen Black ldn-untested;online playable 2021-04-08 12:46:18
1584 010014A00C5E0000 Kin'iro no Corda Octave playable 2020-09-22 13:23:12
1585 010089000F0E8000 Kine UE4 playable 2022-09-14 14:28:37
1586 0100E6B00FFBA000 King Lucas playable 2022-09-21 19:43:23
1587 0100B1300783E000 King Oddball playable 2020-05-13 13:47:57
1612 01009EF00DDB4000 Knockout City™ services;online-broken boots 2022-12-09 09:48:58
1613 0100C57019BA2000 Koa and the Five Pirates of Mara gpu ingame 2024-07-11 16:14:44
1614 01001E500401C000 Koi DX playable 2020-05-11 21:37:51
1615 010052300F612000 Koi no Hanasaku Hyakkaen 32-bit;gpu;nvdec ingame 2020-10-03 14:17:10
1616 01005D200C9AA000 Koloro playable 2022-08-03 12:34:02
1617 0100464009294000 Kona playable 2022-08-03 12:48:19
1618 010016C011AAA000 Kono Subarashii Sekai ni Shukufuku o Kono Yokubo no Isho ni Choai o playable 2023-04-26 09:51:08
1779 0100EC000CE24000 Mech Rage playable 2020-11-18 12:30:16
1780 0100C4F005EB4000 Mecho Tales playable 2022-08-04 17:03:19
1781 0100E4600D31A000 Mechstermination Force playable 2024-07-04 05:39:15
1782 01007580124C0000 Medarot Classics Plus Kabuto Ver playable 2020-11-21 11:31:18
1783 0100228012682000 Medarot Classics Plus Kuwagata Ver playable 2020-11-21 11:30:40
1784 0100BBC00CB9A000 Mega Mall Story slow playable 2022-08-04 17:10:58
1785 0100B0C0086B0000 Mega Man 11 playable 2021-04-26 12:07:53
1786 010038E016264000 Mega Man Battle Network Legacy Collection Vol. 1 playable 2023-04-25 03:55:57
1797 0100B360068B2000 Mekorama gpu boots 2021-06-17 16:37:21
1798 01000FA010340000 Melbits World nvdec;online menus 2021-11-26 13:51:22
1799 0100F68019636000 Melon Journey playable 2023-04-23 21:20:01
1800 010079C012896000 Memories Off -Innocent Fille- for Dearest playable 2020-08-04 07:31:22
1801 010062F011E7C000 Memory Lane UE4 playable 2022-10-05 14:31:03
1802 0100EBE00D5B0000 Meow Motors UE4;gpu ingame 2020-12-18 00:24:01
1803 0100273008FBC000 Mercenaries Saga Chronicles playable 2021-01-10 12:48:19
1873 010093A01305C000 Monster Hunter Rise Demo online-broken;ldn-works;demo playable 2022-10-18 23:04:17
1874 0100E21011446000 Monster Hunter Stories 2: Wings of Ruin services ingame 2022-07-10 19:27:30
1875 010042501329E000 MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version demo playable 2022-11-13 22:20:26
1876 0100C51003B46000 Monster Hunter XX Demo 32-bit;cpu nothing 2020-03-22 10:12:28
1877 0100C3800049C000 Monster Hunter XX Nintendo Switch Ver ( Double Cross ) playable 2024-07-21 14:08:09
1878 010088400366E000 Monster Jam Crush It! UE4;nvdec;online playable 2021-04-08 19:29:27
1879 010095C00F354000 Monster Jam Steel Titans crash;nvdec;UE4 menus 2021-11-14 09:45:38
1917 010035901046C000 Mushroom Quest playable 2020-05-17 13:07:08
1918 0100700006EF6000 Mushroom Wars 2 nvdec playable 2020-09-28 15:26:08
1919 010046400F310000 Music Racer playable 2020-08-10 08:51:23
1920 0100153006300000 Musou Orochi 2 Ultimate crash;nvdec boots 2021-04-09 19:39:16
1921 0100F6000EAA8000 Must Dash Amigos playable 2022-09-20 16:45:56
1922 01007B6006092000 MUSYNX playable 2020-05-08 14:24:43
1923 0100C3E00ACAA000 Mutant Football League: Dynasty Edition online-broken playable 2022-08-05 17:01:51
1948 0100A6F00AC70000 NAIRI: Tower of Shirin nvdec playable 2020-08-09 19:49:12
1949 010002F001220000 NAMCO MUSEUM ldn-untested playable 2024-08-13 07:52:21
1950 0100DAA00AEE6000 NAMCO MUSEUM™ ARCADE PAC™ playable 2021-06-07 21:44:50
1951 010039F010E14000 NAMCOT COLLECTION audio playable 2020-06-25 13:35:22
1952 010072B00BDDE000 Narcos: Rise of the Cartels UE4;crash;nvdec boots 2021-03-22 13:18:47
1953 01006BB00800A000 NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst nvdec playable 2024-06-16 14:58:05
1954 010084D00CF5E000 NARUTO SHIPPUDEN™: Ultimate Ninja® STORM 4 ROAD TO BORUTO playable 2024-06-29 13:04:22
2089 0100F9D00C186000 Olympia Soiree playable 2022-12-04 21:07:12
2090 0100A8B00E14A000 Olympic Games Tokyo 2020 – The Official Video Game™ ldn-untested;nvdec;online playable 2021-01-06 01:20:24
2091 01001D600E51A000 Omega Labyrinth Life playable 2021-02-23 21:03:03
2092 01005DE00CA34000 Omega Vampire nvdec playable 2020-10-17 19:15:35
2093 0100CDC00C40A000 Omensight: Definitive Edition UE4;crash;nvdec ingame 2020-07-26 01:45:14
2094 01006DB00D970000 OMG Zombies! 32-bit playable 2021-04-12 18:04:45
2095 010014E017B14000 OMORI playable 2023-01-07 20:21:02
2096 0100A5F011800000 Once Upon A Coma nvdec playable 2020-08-01 12:09:39
2097 0100BD3006A02000 One More Dungeon playable 2021-01-06 09:10:58
2098 010076600FD64000 One Person Story playable 2020-07-14 11:51:02
2099 0100774009CF6000 ONE PIECE Pirate Warriors 3 Deluxe Edition nvdec playable 2020-05-10 06:23:52
2184 010062B01525C000 Persona 4 Golden playable 2024-08-07 17:48:07
2185 01005CA01580E000 Persona 5 Royal gpu ingame 2024-08-17 21:45:15
2186 010087701B092000 Persona 5 Tactica playable 2024-04-01 22:21:03
2187 0100E4F010D92000 Persona 5: Scramble deadlock boots 2020-10-04 03:22:29
2188 0100801011C3E000 Persona® 5 Strikers nvdec;mac-bug playable 2023-09-26 09:36:01
2189 010044400EEAE000 Petoons Party nvdec playable 2021-03-02 21:07:58
2190 010053401147C000 PGA TOUR 2K21 deadlock;nvdec ingame 2022-10-05 21:53:50
2273 0100D1C01C194000 Powerful Pro Baseball 2024-2025 gpu ingame 2024-08-25 06:40:48
2274 01008E100E416000 PowerSlave Exhumed gpu ingame 2023-07-31 23:19:10
2275 010054F01266C000 Prehistoric Dude gpu ingame 2020-10-12 12:38:48
2276 0100DB200D3E4000 Pretty Princess Magical Coordinate playable 2020-10-15 11:43:41
2277 01007F00128CC000 Pretty Princess Party playable 2022-10-19 17:23:58
2278 010009300D278000 Preventive Strike nvdec playable 2022-10-06 10:55:51
2279 0100210019428000 Prince of Persia The Lost Crown crash ingame 2024-06-08 21:31:58
2294 0100ACE00DAB6000 Project Nimbus: Complete Edition nvdec;UE4;vulkan-backend-bug playable 2022-08-10 17:35:43
2295 01002980140F6000 Project TRIANGLE STRATEGY™ Debut Demo UE4;demo playable 2022-10-24 21:40:27
2296 0100BDB01150E000 Project Warlock playable 2020-06-16 10:50:41
2297 01009F100BC52000 Psikyo Collection Vol 1 32-bit playable 2020-10-11 13:18:47
2298 0100A2300DB78000 Psikyo Collection Vol. 3 ingame 2021-06-07 02:46:23
2299 01009D400C4A8000 Psikyo Collection Vol.2 32-bit playable 2021-06-07 03:22:07
2300 01007A200F2E2000 Psikyo Shooting Stars Alpha 32-bit playable 2021-04-13 12:03:43
2301 0100D7400F2E4000 Psikyo Shooting Stars Bravo 32-bit playable 2021-06-14 12:09:07
2302 0100EC100A790000 PSYVARIAR DELTA nvdec playable 2021-01-20 13:01:46
2303 0100AE700F184000 Puchitto kurasutā Need-Update;crash;services menus 2020-07-04 16:44:28
2304 0100D61010526000 Pulstario playable 2022-10-06 11:02:01
2305 01009AE00B788000 Pumped BMX Pro nvdec;online-broken playable 2022-09-20 17:40:50
2306 01006C10131F6000 Pumpkin Jack nvdec;UE4 playable 2022-10-13 12:52:32
2325 0100DCF00F13A000 Queen's Quest 4: Sacred Truce nvdec playable 2022-10-13 12:59:21
2326 0100492012378000 Quell gpu ingame 2021-06-11 15:59:53
2327 01001DE005012000 Quest of Dungeons playable 2021-06-07 10:29:22
2328 010067D011E68000 QuietMansion2 playable 2020-09-03 14:59:35
2329 0100AF100EE76000 Quiplash 2 InterLASHional: The Say Anything Party Game! online-working playable 2022-10-19 17:43:45
2330 0100E5400BE64000 R-Type Dimensions EX playable 2020-10-09 12:04:43
2331 0100F930136B6000 R-Type® Final 2 slow;nvdec;UE4 ingame 2022-10-30 21:46:29
2383 01007A800D520000 Refunct UE4 playable 2020-12-15 22:46:21
2384 0100FDF0083A6000 Regalia: Of Men and Monarchs - Royal Edition playable 2022-08-11 12:24:01
2385 01005FD00F15A000 Regions of Ruin playable 2020-08-05 11:38:58
2386 0100B5800C0E4000 Reine des Fleurs cpu;crash boots 2020-09-27 18:50:39
2387 0100F1900B144000 REKT! High Octane Stunts online playable 2020-09-28 12:33:56
2388 01002AD013C52000 Relicta nvdec;UE4 playable 2022-10-31 12:48:33
2389 010095900B436000 RemiLore playable 2021-06-03 18:58:15
2495 01002DF00F76C000 SAMURAI SHODOWN UE4;crash;nvdec menus 2020-09-06 02:17:00
2496 0100F6800F48E000 SAMURAI SHODOWN NEOGEO COLLECTION nvdec playable 2021-06-14 17:12:56
2497 0100B6501A360000 Samurai Warrior playable 2023-02-27 18:42:38
2498 01000EA00B23C000 Sangoku Rensenki ~Otome no Heihou!~ gpu;nvdec ingame 2020-10-17 19:13:14
2499 0100A4700BC98000 Satsujin Tantei Jack the Ripper playable 2021-06-21 16:32:54
2500 0100F0000869C000 Saturday Morning RPG nvdec playable 2022-08-12 12:41:50
2501 01006EE00380C000 Sausage Sports Club gpu ingame 2021-01-10 05:37:17
2532 010054400D2E6000 SEGA AGES Virtua Racing online-broken playable 2023-01-29 17:08:39
2533 01001E700AC60000 SEGA AGES Wonder Boy: Monster Land online playable 2021-05-05 16:28:25
2534 0100B3C014BDA000 SEGA Genesis™ – Nintendo Switch Online crash;regression nothing 2022-04-11 07:27:21
2535 0100F7300B24E000 SEGA Mega Drive Classics online playable 2021-01-05 11:08:00
2536 01009840046BC000 Semispheres playable 2021-01-06 23:08:31
2537 0100D1800D902000 SENRAN KAGURA Peach Ball playable 2021-06-03 15:12:10
2538 0100E0C00ADAC000 SENRAN KAGURA Reflexions playable 2020-03-23 19:15:23
2585 0100B2E00F13E000 Shipped playable 2020-11-21 14:22:32
2586 01000E800FCB4000 Ships playable 2021-06-11 16:14:37
2587 01007430122D0000 Shiren the Wanderer: The Tower of Fortune and the Dice of Fate nvdec playable 2022-10-20 11:44:36
2588 010027300A660000 Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~ cpu;crash boots 2020-09-27 19:01:25
2589 01000244016BAE00 Shiro0 gpu ingame 2024-01-13 08:54:39
2590 0100CCE00DDB6000 Shoot 1UP DX playable 2020-12-13 12:32:47
2591 01001180021FA000 Shovel Knight: Specter of Torment playable 2020-05-30 08:34:17
2626 0100C52011460000 Sky: Children of the Light cpu;online-broken nothing 2023-02-23 10:57:10
2627 010041C01014E000 Skybolt Zack playable 2021-04-12 18:28:00
2628 0100A0A00D1AA000 SKYHILL playable 2021-03-05 15:19:11
2629 0100CCC0002E6000 Skylanders Imaginators crash;services boots 2020-05-30 18:49:18
2630 010021A00ABEE000 SKYPEACE playable 2020-05-29 14:14:30
2631 0100EA400BF44000 SkyScrappers playable 2020-05-28 22:11:25
2632 0100F3C00C400000 SkyTime slow ingame 2020-05-30 09:24:51
2681 01005EA01C0FC000 SONIC X SHADOW GENERATIONS crash ingame 2025-01-07 04:20:45
2682 010064F00C212000 Soul Axiom Rebooted nvdec;slow ingame 2020-09-04 12:41:01
2683 0100F2100F0B2000 Soul Searching playable 2020-07-09 18:39:07
2684 01008F2005154000 South Park™: The Fractured but Whole™ - Standard Edition slow;online-broken slow;online-broken;vulkan-backend-bug;gpu playable ingame 2024-07-08 17:47:28 2025-01-21 17:35:10
2685 0100B9F00C162000 Space Blaze playable 2020-08-30 16:18:05
2686 010005500E81E000 Space Cows UE4;crash menus 2020-06-15 11:33:20
2687 0100707011722000 Space Elite Force playable 2020-11-27 15:21:05
2797 0100681011B56000 Struggling playable 2020-10-15 20:37:03
2798 0100AF000B4AE000 Stunt Kite Party nvdec playable 2021-01-25 17:16:56
2799 0100C5500E7AE000 STURMWIND EX audio;32-bit playable 2022-09-16 12:01:39
2800 01001C1009892000 Subarashiki Kono Sekai -Final Remix- services;slow ingame 2020-02-10 16:21:51
2801 010001400E474000 Subdivision Infinity DX UE4;crash boots 2021-03-03 14:26:46
2802 0100E6400BCE8000 Sublevel Zero Redux playable 2022-09-16 12:30:03
2803 0100EDA00D866000 Submerged nvdec;UE4;vulkan-backend-bug playable 2022-08-16 15:17:01
2846 0100284007D6C000 Super One More Jump playable 2022-08-17 16:47:47
2847 01001F90122B2000 Super Punch Patrol playable 2024-07-12 19:49:02
2848 0100331005E8E000 Super Putty Squad gpu;32-bit ingame 2024-04-29 15:51:54
2849 01006C900CC60000 SUPER ROBOT WARS T online playable 2021-03-25 11:00:40
2850 0100CA400E300000 SUPER ROBOT WARS V online playable 2020-06-23 12:56:37
2851 010026800E304000 SUPER ROBOT WARS X online playable 2020-08-05 19:18:51
2852 01004CF00A60E000 Super Saurio Fly nvdec playable 2020-08-06 13:12:14
2853 010039700D200000 Super Skelemania playable 2020-06-07 22:59:50
2854 01006A800016E000 Super Smash Bros.™ Ultimate gpu;crash;nvdec;ldn-works;intel-vendor-bug ingame 2024-09-14 23:05:21
3014 010085A00C5E8000 The Lord of the Rings: Adventure Card Game - Definitive Edition online-broken menus 2022-09-16 15:19:32
3015 01008A000A404000 The Lost Child nvdec playable 2021-02-23 15:44:20
3016 0100BAB00A116000 The Low Road playable 2021-02-26 13:23:22
3017 01005F3006AFE000 The Mahjong Needs Update;crash;services nothing 2021-04-01 22:06:22
3018 0100DC300AC78000 The Messenger playable 2020-03-22 13:51:37
3019 0100DEC00B2BC000 The Midnight Sanctuary nvdec;UE4;vulkan-backend-bug playable 2022-10-03 17:17:32
3020 0100F1B00B456000 The MISSING: J.J. Macfield and the Island of Memories playable 2022-08-22 19:36:18
3060 010064E00ECBC000 The Unicorn Princess playable 2022-09-16 16:20:56
3061 0100BCF00E970000 The Vanishing of Ethan Carter UE4 playable 2021-06-09 17:14:47
3062 0100D0500B0A6000 The VideoKid nvdec playable 2021-01-06 09:28:24
3063 01008CF00BA38000 The Voice services menus 2020-07-28 20:48:49
3064 010056E00B4F4000 The Walking Dead: A New Frontier playable 2022-09-21 13:40:48
3065 010099100B6AC000 The Walking Dead: Season Two playable 2020-08-09 12:57:06
3066 010029200B6AA000 The Walking Dead: The Complete First Season playable 2021-06-04 13:10:56
3348 01001C400482C000 Wunderling DX audio;crash ingame 2022-09-10 13:20:12
3349 01003B401148E000 Wurroom playable 2020-10-07 22:46:21
3350 010081700EDF4000 WWE 2K Battlegrounds nvdec;online-broken;UE4 playable 2022-10-07 12:44:40
3351 010009800203E000 WWE 2K18 nvdec nvdec;online-broken playable ingame 2023-10-21 17:22:01 2025-01-17 11:36:56
3352 0100DF100B97C000 X-Morph: Defense playable 2020-06-22 11:05:31
3353 0100D0B00FB74000 XCOM® 2 Collection gpu;crash ingame 2022-10-04 09:38:30
3354 0100CC9015360000 XEL gpu ingame 2022-10-03 10:19:39
3376 010022F00DA66000 Yooka-Laylee and the Impossible Lair playable 2021-03-05 17:32:21
3377 01006000040C2000 Yoshi’s Crafted World™ gpu;audout ingame 2021-08-30 13:25:51
3378 0100AE800C9C6000 Yoshi’s Crafted World™ Demo gpu boots 2020-12-16 14:57:40
3379 0100BBA00B23E000 Yoshiwara Higanbana Kuon no Chigiri nvdec playable 2020-10-17 19:14:46
3380 01003A400C3DA800 YouTube playable 2024-06-08 05:24:10
3381 00100A7700CCAA40 Youtubers Life00 nvdec playable 2022-09-03 14:56:19
3382 0100E390124D8000 Ys IX: Monstrum Nox playable 2022-06-12 04:14:42
3386 01002D60188DE000 Yu-Gi-Oh! Rush Duel: Dawn of the Battle Royale!! Let's Go! Go Rush!! crash ingame 2023-03-17 01:54:01
3387 010037D00DBDC000 YU-NO: A girl who chants love at the bound of this world. nvdec playable 2021-01-26 17:03:52
3388 0100B56011502000 Yumeutsutsu Re:After playable 2022-11-20 16:09:06
3389 0100DE200C0DA000 Yunohana Spring! - Mellow Times - audio;crash menus 2020-09-27 19:27:40
3390 0100307011C44000 Yuppie Psycho: Executive Edition crash ingame 2020-12-11 10:37:06
3391 0100FC900963E000 Yuri playable 2021-06-11 13:08:50
3392 010092400A678000 Zaccaria Pinball online-broken playable 2022-09-03 15:44:28
3397 0100AAC00E692000 Zenith playable 2022-09-17 09:57:02
3398 0100A6A00894C000 ZERO GUNNER 2- for Nintendo Switch playable 2021-01-04 20:17:14
3399 01004B001058C000 Zero Strain services;UE4 menus 2021-11-10 07:48:32
3400 010021300F69E000 Zettai kaikyu gakuen gpu;nvdec ingame 2020-08-25 15:15:54
3401 0100D7B013DD0000 Ziggy the Chaser playable 2021-02-04 20:34:27
3402 010086700EF16000 ZikSquare gpu ingame 2021-11-06 02:02:48
3403 010069C0123D8000 Zoids Wild Blast Unleashed nvdec playable 2022-10-15 11:26:59
3409 0100CD300A1BA000 Zombillie playable 2020-07-23 17:42:23
3410 01001EE00A6B0000 Zotrix: Solar Division playable 2021-06-07 20:34:05
3411 0100B9B00C6A4000 この世の果てで恋を唄う少女YU-NO audio ingame 2021-01-22 07:00:16
3412 0100E8600C504000 スーパーファミコン Nintendo Switch Online slow ingame 2020-03-14 05:48:38
3413 01000BB01CB8A000 トラブル・マギア ~訳アリ少女は未来を勝ち取るために異国の魔法学校へ留学します~(Trouble Magia ~Wakeari Shoujo wa Mirai o Kachitoru Tame ni Ikoku no Mahou Gakkou e Ryuugaku Shimasu~) nothing 2024-09-28 07:03:14
3414 010065500B218000 メモリーズオフ - Innocent Fille playable 2022-12-02 17:36:48
3415 010032400E700000 二ノ国 白き聖灰の女王 services;32-bit menus 2023-04-16 17:11:06
3421 0100936018EB4000 牧場物語 Welcome!ワンダフルライフ crash ingame 2023-04-25 19:43:52
3422 0100F4401940A000 超探偵事件簿 レインコード (Master Detective Archives: Rain Code) crash ingame 2024-02-12 20:58:31
3423 010064801A01C000 超次元ゲイム ネプテューヌ GameMaker R:Evolution crash nothing 2023-10-30 22:37:40
3424 0100F3400332C000 ゼノブレイド2 deadlock;amd-vendor-bug ingame 2024-03-28 14:31:41

View File

@ -1,4 +1,4 @@
using Gommon;
using Gommon;
using Ryujinx.Common.Configuration;
using System;
using System.Linq;
@ -14,6 +14,7 @@ namespace Ryujinx.Common
{
switch (currentBackend)
{
case GraphicsBackend.Metal when !OperatingSystem.IsMacOS():
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
return GraphicsBackend.Vulkan;
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
@ -28,18 +29,28 @@ namespace Ryujinx.Common
public static readonly string[] GreatMetalTitles =
[
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"010076f0049a2000", // Bayonetta
"0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5
"0100187003A36000", // Pokémon: Let's Go, Evoli!
"010075a016a3a000", // Persona 4 Arena Ultimax
"0100187003A36000", // Pokémon: Let's Go, Eevee!
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
// These ones have small issues, but those happen on Vulkan as well:
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"01009510001ca000", // Fast RMX
"01005CA01580E000", // Persona 5 Royale
"0100000000010000", // Super Mario Odyssey
//Isaac claims it has a issue in level 2, but I am not able to replicate it on my M3. More testing would be appreciated:
"010015100b514000", // Super Mario Bros. Wonder
];
public static string GetDiscordGameAsset(string titleId)
@ -47,93 +58,117 @@ namespace Ryujinx.Common
public static readonly string[] DiscordGameAssetKeys =
[
"010055d009f78000", // Fire Emblem: Three Houses
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
//All games are in Alphabetical order by Game name.
//Dragon Quest Franchise
"010008900705c000", // Dragon Quest Builders
"010042000a986000", // Dragon Quest Builders 2
//Fire Emblem Franchise
"0100a6301214e000", // Fire Emblem Engage
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
"010055d009f78000", // Fire Emblem: Three Houses
"0100f15003e64000", // Fire Emblem Warriors
"010071f0143ea000", // Fire Emblem Warriors: Three Hopes
"01007e3006dda000", // Kirby Star Allies
//Kirby Franchise
"01004d300c5ae000", // Kirby and the Forgotten Land
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01003fb00c5a8000", // Super Kirby Clash
"0100227010460000", // Kirby Fighters 2
"0100a8e016236000", // Kirby's Dream Buffet
"0100227010460000", // Kirby Fighters 2
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01007e3006dda000", // Kirby Star Allies
"01003fb00c5a8000", // Super Kirby Clash
//The Zelda Franchise
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
"01002da013484000", // The Legend of Zelda: Skyward Sword HD
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
"01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
//Luigi Franchise
"010048701995e000", // Luigi's Mansion 2 HD
"0100dca0064a6000", // Luigi's Mansion 3
//Metroid Franchise
"010093801237c000", // Metroid Dread
"010012101468c000", // Metroid Prime Remastered
"0100000000010000", // SUPER MARIO ODYSSEY
"0100ea80032ea000", // Super Mario Bros. U Deluxe
"01009b90006dc000", // Super Mario Maker 2
"010049900f546000", // Super Mario 3D All-Stars
"010049900F546001", // ^ 64
"010049900F546002", // ^ Sunshine
"010049900F546003", // ^ Galaxy
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010015100b514000", // Super Mario Bros. Wonder
"0100152000022000", // Mario Kart 8 Deluxe
"010036b0034e4000", // Super Mario Party
"01006fe013472000", // Mario Party Superstars
"0100965017338000", // Super Mario Party Jamboree
//Monster Hunter Franchise
"0100770008dd8000", // Monster Hunter Generations Ultimate
"0100b04011742000", // Monster Hunter Rise
//Mario Franchise
"01006d0017f7a000", // Mario & Luigi: Brothership
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"010067300059a000", // Mario + Rabbids: Kingdom Battle
"0100317013770000", // Mario + Rabbids: Sparks of Hope
"0100c9c00e25c000", // Mario Golf: Super Rush
"0100152000022000", // Mario Kart 8 Deluxe
"01006fe013472000", // Mario Party Superstars
"010019401051c000", // Mario Strikers: Battle League
"0100bde00862a000", // Mario Tennis Aces
"0100b99019412000", // Mario vs. Donkey Kong
"010049900f546000", // Super Mario 3D All-Stars
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010049900F546001", // Super Mario 64
"0100ea80032ea000", // Super Mario Bros. U Deluxe
"010015100b514000", // Super Mario Bros. Wonder
"010049900F546003", // Super Mario Galaxy
"01009b90006dc000", // Super Mario Maker 2
"0100000000010000", // SUPER MARIO ODYSSEY
"010036b0034e4000", // Super Mario Party
"0100965017338000", // Super Mario Party Jamboree
"0100bc0018138000", // Super Mario RPG
"010049900F546002", // Super Mario Sunshine
"0100a3900c3e2000", // Paper Mario: The Origami King
"0100ecd018ebe000", // Paper Mario: The Thousand-Year Door
"0100bc0018138000", // Super Mario RPG
"0100bde00862a000", // Mario Tennis Aces
"0100c9c00e25c000", // Mario Golf: Super Rush
"010019401051c000", // Mario Strikers: Battle League
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"0100b99019412000", // Mario vs. Donkey Kong
//Pikmin Franchise
"0100aa80194b0000", // Pikmin 1
"0100d680194b2000", // Pikmin 2
"0100f4c009322000", // Pikmin 3 Deluxe
"0100b7c00933a000", // Pikmin 4
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"0100187003a36000", // Pokémon: Let's Go Eevee!
"0100abf008968000", // Pokémon Sword
"01008db008c2c000", // Pokémon Shield
//The Pokémon Franchise
"0100f4300bf2c000", // New Pokémon Snap
"0100000011d90000", // Pokémon Brilliant Diamond
"010018e011d92000", // Pokémon Shining Pearl
"01001f5010dfa000", // Pokémon Legends: Arceus
"01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX
"0100a3d008c5c000", // Pokémon Scarlet
"01008db008c2c000", // Pokémon Shield
"010018e011d92000", // Pokémon Shining Pearl
"0100abf008968000", // Pokémon Sword
"01008f6008c5e000", // Pokémon Violet
"0100b3f000be2000", // Pokkén Tournament DX
"0100f4300bf2c000", // New Pokémon Snap
"0100187003a36000", // Pokémon: Let's Go Eevee!
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"01003bc0000a0000", // Splatoon 2 (US)
//Splatoon Franchise
"0100f8f0000a2000", // Splatoon 2 (EU)
"01003c700009c000", // Splatoon 2 (JP)
"01003bc0000a0000", // Splatoon 2 (US)
"0100c2500fc20000", // Splatoon 3
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
"010040600c5ce000", // Tetris 99
"0100277011f1a000", // Super Mario Bros. 35
"0100ad9012510000", // PAC-MAN 99
//NSO Membership games
"0100ccf019c8c000", // F-ZERO 99
"0100d870045b6000", // NES - Nintendo Switch Online
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100c62011050000", // GB - Nintendo Switch Online
"010012f017576000", // GBA - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100d870045b6000", // NES - Nintendo Switch Online
"0100ad9012510000", // PAC-MAN 99
"010040600c5ce000", // Tetris 99
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100277011f1a000", // Super Mario Bros. 35
//Misc Nintendo 1st party games
"01000320000cc000", // 1-2 Switch
"0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp
"01006f8002326000", // Animal Crossing: New Horizons
@ -148,33 +183,44 @@ namespace Ryujinx.Common
"01006a800016e000", // Super Smash Bros. Ultimate
"0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore
//Bayonetta Franchise
"010076f0049a2000", // Bayonetta
"01007960049a0000", // Bayonetta 2
"01004a4010fea000", // Bayonetta 3
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
//Persona Franchise
"0100dcd01525a000", // Persona 3 Portable
"010062b01525c000", // Persona 4 Golden
"010075a016a3a000", // Persona 4 Arena Ultimax
"010062b01525c000", // Persona 4 Golden
"01005ca01580e000", // Persona 5 Royal
"0100801011c3e000", // Persona 5 Strikers
"010087701b092000", // Persona 5 Tactica
"01009aa000faa000", // Sonic Mania
//Sonic Franchise
"01004ad014bf0000", // Sonic Frontiers
"01009aa000faa000", // Sonic Mania
"01005ea01c0fc000", // SONIC X SHADOW GENERATIONS
"01005ea01c0fc001", // ^
//Xenoblade Franchise
"0100ff500e34a000", // Xenoblade Chronicles - Definitive Edition
"0100e95004038000", // Xenoblade Chronicles 2
"010074f013262000", // Xenoblade Chronicles 3
//Misc Games
"010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance
"0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast
"010085900337e000", // Death Squared
"01001b300b9be000", // Diablo III: Eternal Collection
"01008c8012920000", // Dying Light Platinum Edition
"01001cc01b2d4000", // Goat Simulator 3
"01003620068ea000", // Hand of Fate 2
"010085500130a000", // Lego City: Undercover
"010073c01af34000", // LEGO Horizon Adventures
"0100770008dd8000", // Monster Hunter Generations Ultimate
"0100b04011742000", // Monster Hunter Rise
"0100853015e86000", // No Man's Sky
"01007bb017812000", // Portal
"0100abd01785c000", // Portal 2
@ -190,6 +236,8 @@ namespace Ryujinx.Common
"01000a10041ea000", // The Elder Scrolls V: Skyrim
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
"010080b00ad66000", // Undertale
"010069401adb8000", // Unicorn Overlord
"0100534009ff2000", // Yonder - The cloud catcher chronicles
];
}
}

View File

@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
private static string GetDiskCachePath()
{
return GraphicsConfig.EnableShaderCache && GraphicsConfig.TitleId != null
? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId, "cache", "shader")
? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId.ToLower(), "cache", "shader")
: null;
}

View File

@ -26,10 +26,20 @@ namespace Ryujinx.HLE.HOS.Applets
{
_normalSession = normalSession;
_interactiveSession = interactiveSession;
// TODO(jduncanator): Parse PlayerSelectConfig from input data
_normalSession.Push(BuildResponse());
UserProfile selected = _system.Device.UIHandler.ShowPlayerSelectDialog();
if (selected == null)
{
_normalSession.Push(BuildResponse());
}
else if (selected.UserId == new UserId("00000000000000000000000000000080"))
{
_normalSession.Push(BuildGuestResponse());
}
else
{
_normalSession.Push(BuildResponse(selected));
}
AppletStateChanged?.Invoke(this, null);
_system.ReturnFocus();
@ -37,16 +47,34 @@ namespace Ryujinx.HLE.HOS.Applets
return ResultCode.Success;
}
private byte[] BuildResponse()
private byte[] BuildResponse(UserProfile selectedUser)
{
UserProfile currentUser = _system.AccountManager.LastOpenedUser;
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write((ulong)PlayerSelectResult.Success);
currentUser.UserId.Write(writer);
selectedUser.UserId.Write(writer);
return stream.ToArray();
}
private byte[] BuildGuestResponse()
{
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write(new byte());
return stream.ToArray();
}
private byte[] BuildResponse()
{
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write((ulong)PlayerSelectResult.Failure);
return stream.ToArray();
}

View File

@ -176,9 +176,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
if (isApplication && lowestCpuCore == 0 && highestCpuCore != 2)
Ryujinx.Common.Logging.Logger.Error?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}! Report this to @LotP on the Ryujinx/Ryubing discord server (discord.gg/ryujinx)!");
else if (isApplication)
if (isApplication)
Ryujinx.Common.Logging.Logger.Info?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}");
break;

View File

@ -56,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
ProfilesJson profilesJson = JsonHelper.DeserializeFromFile(_profilesJsonPath, _serializerContext.ProfilesJson);
return profilesJson.Profiles
.FindFirst(profile => profile.AccountState == AccountState.Open)
.FindFirst(profile => profile.UserId == profilesJson.LastOpened)
.Convert(profileJson => new UserProfile(new UserId(profileJson.UserId), profileJson.Name,
profileJson.Image, profileJson.LastModifiedTimestamp));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -244,6 +244,15 @@ namespace Ryujinx.HLE.HOS.Services.Settings
return ResultCode.Success;
}
[CommandCmif(68)]
// GetSerialNumber() -> buffer<nn::settings::system::SerialNumber, 0x16>
public ResultCode GetSerialNumber(ServiceCtx context)
{
context.ResponseData.Write(Encoding.ASCII.GetBytes("RYU00000000000"));
return ResultCode.Success;
}
[CommandCmif(77)]
// GetDeviceNickName() -> buffer<nn::settings::system::DeviceNickName, 0x16>
public ResultCode GetDeviceNickName(ServiceCtx context)

View File

@ -51,6 +51,9 @@ namespace Ryujinx.HLE.HOS.Services.Spl
context.ResponseData.Write(configValue);
if (result == SmcResult.Success)
return ResultCode.Success;
return (ResultCode)((int)result << 9) | ResultCode.ModuleId;
}

View File

@ -48,6 +48,7 @@
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnB.png" />
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_KeyF6.png" />
<EmbeddedResource Include="HOS\Services\Account\Acc\DefaultUserImage.jpg" />
<EmbeddedResource Include="HOS\Services\Account\Acc\GuestUserImage.jpg" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
namespace Ryujinx.HLE.UI
@ -59,5 +60,11 @@ namespace Ryujinx.HLE.UI
/// Gets fonts and colors used by the host.
/// </summary>
IHostUITheme HostUITheme { get; }
/// <summary>
/// Displays the player select dialog and returns the selected profile.
/// </summary>
UserProfile ShowPlayerSelectDialog();
}
}

View File

@ -489,7 +489,7 @@ namespace Ryujinx.Ava
Dispatcher.UIThread.InvokeAsync(() =>
{
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version);
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
});
_viewModel.SetUiProgressHandlers(Device);
@ -674,7 +674,7 @@ namespace Ryujinx.Ava
public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
{
InitializeSwitchInstance();
InitEmulatedSwitch();
MainWindow.UpdateGraphicsConfig();
SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
@ -757,6 +757,8 @@ namespace Ryujinx.Ava
{
romFsFiles = Directory.GetFiles(ApplicationPath, "*.romfs");
}
Logger.Notice.Print(LogClass.Application, $"Loading unpacked content archive from '{ApplicationPath}'.");
if (romFsFiles.Length > 0)
{
@ -783,6 +785,8 @@ namespace Ryujinx.Ava
}
else if (File.Exists(ApplicationPath))
{
Logger.Notice.Print(LogClass.Application, $"Loading content archive from '{ApplicationPath}'.");
switch (Path.GetExtension(ApplicationPath).ToLowerInvariant())
{
case ".xci":
@ -872,7 +876,7 @@ namespace Ryujinx.Ava
Device?.System.TogglePauseEmulation(false);
_viewModel.IsPaused = false;
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version);
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
}
@ -881,11 +885,11 @@ namespace Ryujinx.Ava
Device?.System.TogglePauseEmulation(true);
_viewModel.IsPaused = true;
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, LocaleManager.Instance[LocaleKeys.Paused]);
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar, LocaleManager.Instance[LocaleKeys.Paused]);
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
}
private void InitializeSwitchInstance()
private void InitEmulatedSwitch()
{
// Initialize KeySet.
VirtualFileSystem.ReloadKeySet();
@ -1040,7 +1044,7 @@ namespace Ryujinx.Ava
_viewModel.WindowState = WindowState.FullScreen;
}
if (_viewModel.WindowState is WindowState.FullScreen)
if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUI)
{
_viewModel.ShowMenuAndStatusBar = false;
}

View File

@ -0,0 +1,13 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style Selector="MenuItem.withCheckbox Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="MenuItem.withCheckbox ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</Styles>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
using Avalonia.Controls.Notifications;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Gommon;
using LibHac;
using LibHac.Account;
using LibHac.Common;
@ -15,6 +15,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
@ -295,22 +296,150 @@ namespace Ryujinx.Ava.Common
};
extractorThread.Start();
}
public static void ExtractAoc(string destination, string updateFilePath, string updateName)
{
var cancellationToken = new CancellationTokenSource();
UpdateWaitWindow waitingDialog = new(
RyujinxApp.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, NcaSectionType.Data, Path.GetFileName(updateFilePath)),
cancellationToken);
Thread extractorThread = new(() =>
{
Dispatcher.UIThread.Post(waitingDialog.Show);
using FileStream file = new(updateFilePath, FileMode.Open, FileAccess.Read);
Nca publicDataNca = null;
string extension = Path.GetExtension(updateFilePath).ToLower();
if (extension is ".nsp")
{
var pfsTemp = new PartitionFileSystem();
pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
IFileSystem pfs = pfsTemp;
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
if (nca.Header.ContentType is NcaContentType.PublicData && nca.SectionExists(NcaSectionType.Data))
{
publicDataNca = nca;
}
}
}
if (publicDataNca is null)
{
Logger.Error?.Print(LogClass.Application, "Extraction failure. The NCA was not present in the selected file");
Dispatcher.UIThread.InvokeAsync(async () =>
{
waitingDialog.Close();
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]);
});
return;
}
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
int index = Nca.GetSectionIndexFromType(NcaSectionType.Data, publicDataNca.Header.ContentType);
try
{
IFileSystem ncaFileSystem = publicDataNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);
FileSystemClient fsClient = _horizonClient.Fs;
string source = DateTime.Now.ToFileTime().ToString()[10..];
string output = DateTime.Now.ToFileTime().ToString()[10..];
using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem);
using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination));
fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref);
fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref);
(Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/", cancellationToken.Token);
if (!canceled)
{
if (resultCode.Value.IsFailure())
{
Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}");
Dispatcher.UIThread.InvokeAsync(async () =>
{
waitingDialog.Close();
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]);
});
}
else if (resultCode.Value.IsSuccess())
{
Dispatcher.UIThread.Post(waitingDialog.Close);
NotificationHelper.ShowInformation(
RyujinxApp.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
$"{updateName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}");
}
}
fsClient.Unmount(source.ToU8Span());
fsClient.Unmount(output.ToU8Span());
}
catch (ArgumentException ex)
{
Logger.Error?.Print(LogClass.Application, $"{ex.Message}");
Dispatcher.UIThread.InvokeAsync(async () =>
{
waitingDialog.Close();
await ContentDialogHelper.CreateErrorDialog(ex.Message);
});
}
})
{
Name = "GUI.AocExtractorThread",
IsBackground = true,
};
extractorThread.Start();
}
public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName)
{
Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
});
if (!result.HasValue) return;
ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName);
}
public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
{
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle],
AllowMultiple = false,
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
});
if (result.Count == 0)
{
return;
}
if (!result.HasValue) return;
ExtractSection(result[0].Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
}
public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token)

View File

@ -6,7 +6,7 @@ namespace Ryujinx.Ava.Common.Models
public bool IsBundled { get; } = System.IO.Path.GetExtension(ContainerPath)?.ToLower() == ".xci";
public string FileName => System.IO.Path.GetFileName(ContainerPath);
public string TitleIdStr => TitleId.ToString("x16");
public string TitleIdStr => TitleId.ToString("x16").ToUpper();
public ulong TitleIdBase => TitleId & ~0x1FFFUL;
}
}

View File

@ -4,11 +4,11 @@ namespace Ryujinx.Ava.Common
{
public static class ThemeManager
{
public static event EventHandler ThemeChanged;
public static event Action ThemeChanged;
public static void OnThemeChanged()
{
ThemeChanged?.Invoke(null, EventArgs.Empty);
ThemeChanged?.Invoke();
}
}
}

View File

@ -1,6 +1,8 @@
using DiscordRPC;
using Gommon;
using Humanizer;
using Humanizer.Localisation;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common;
@ -45,16 +47,7 @@ namespace Ryujinx.Ava
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
TitleIDs.CurrentApplication.Event += (_, e) =>
{
if (e.NewValue)
SwitchToPlayingState(
ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
Switch.Shared.Processes.ActiveApplication
);
else
SwitchToMainState();
};
TitleIDs.CurrentApplication.Event += (_, e) => Use(e.NewValue);
}
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
@ -75,11 +68,23 @@ namespace Ryujinx.Ava
_discordClient = new DiscordRpcClient(ApplicationId);
_discordClient.Initialize();
_discordClient.SetPresence(_discordPresenceMain);
Use(TitleIDs.CurrentApplication);
}
}
}
public static void Use(Optional<string> titleId)
{
if (titleId.TryGet(out string tid))
SwitchToPlayingState(
ApplicationLibrary.LoadAndSaveMetaData(tid),
Switch.Shared.Processes.ActiveApplication
);
else
SwitchToMainState();
}
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
{
_discordClient?.SetPresence(new RichPresence
@ -93,7 +98,7 @@ namespace Ryujinx.Ava
},
Details = TruncateToByteLength($"Playing {appMeta.Title}"),
State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
? $"Total play time: {appMeta.TimePlayed.Humanize(2, false, maxUnit: TimeUnit.Hour)}"
? $"Total play time: {ValueFormatUtils.FormatTimeSpan(appMeta.TimePlayed)}"
: "Never played",
Timestamps = Timestamps.Now
});

View File

@ -228,8 +228,6 @@ namespace Ryujinx.Headless
_inputConfiguration ??= [];
_enableKeyboard = option.EnableKeyboard;
_enableMouse = option.EnableMouse;
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
@ -301,7 +299,10 @@ namespace Ryujinx.Headless
_userChannelPersistence.ShouldRestart = false;
}
_inputManager.Dispose();
try
{
_inputManager.Dispose();
} catch {}
return;
@ -338,12 +339,12 @@ namespace Ryujinx.Headless
{
string label = state switch
{
LoadState => $"PTC : {current}/{total}",
ShaderCacheState => $"Shaders : {current}/{total}",
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"),
LoadState => "PTC",
ShaderCacheState => "Shaders",
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}")
};
Logger.Info?.Print(LogClass.Application, label);
Logger.Info?.Print(LogClass.Application, $"{label} : {current}/{total}");
}
private static WindowBase CreateWindow(Options options)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,21 +0,0 @@
using System;
namespace Ryujinx.Headless
{
class StatusUpdatedEventArgs(
string vSyncMode,
string dockedMode,
string aspectRatio,
string gameStatus,
string fifoStatus,
string gpuName)
: EventArgs
{
public string VSyncMode = vSyncMode;
public string DockedMode = dockedMode;
public string AspectRatio = aspectRatio;
public string GameStatus = gameStatus;
public string FifoStatus = fifoStatus;
public string GpuName = gpuName;
}
}

View File

@ -26,7 +26,7 @@ namespace Ryujinx.Headless
bool ignoreControllerApplet)
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { }
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_METAL;
protected override void InitializeWindowRenderer()
{

View File

@ -108,8 +108,7 @@ namespace Ryujinx.Headless
}
}
}
private readonly GraphicsDebugLevel _glLogLevel;
private SDL2OpenGLContext _openGLContext;
public OpenGLWindow(
@ -121,15 +120,14 @@ namespace Ryujinx.Headless
bool ignoreControllerApplet)
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
{
_glLogLevel = glLogLevel;
}
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_OPENGL;
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_OPENGL;
protected override void InitializeWindowRenderer()
{
// Ensure to not share this context with other contexts before this point.
SetupOpenGLAttributes(false, _glLogLevel);
SetupOpenGLAttributes(false, GlLogLevel);
nint context = SDL_GL_CreateContext(WindowHandle);
CheckResult(SDL_GL_SetSwapInterval(1));

View File

@ -10,8 +10,6 @@ namespace Ryujinx.Headless
{
class VulkanWindow : WindowBase
{
private readonly GraphicsDebugLevel _glLogLevel;
public VulkanWindow(
InputManager inputManager,
GraphicsDebugLevel glLogLevel,
@ -21,10 +19,9 @@ namespace Ryujinx.Headless
bool ignoreControllerApplet)
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
{
_glLogLevel = glLogLevel;
}
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_VULKAN;
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_VULKAN;
protected override void InitializeWindowRenderer() { }

View File

@ -1,14 +1,15 @@
using Humanizer;
using LibHac.Tools.Fs;
using Ryujinx.Ava;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.Gpu;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
using Ryujinx.HLE.UI;
using Ryujinx.Input;
@ -26,6 +27,7 @@ using static SDL2.SDL;
using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
using Switch = Ryujinx.HLE.Switch;
using UserProfile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
namespace Ryujinx.Headless
{
@ -53,8 +55,6 @@ namespace Ryujinx.Headless
public Switch Device { get; private set; }
public IRenderer Renderer { get; private set; }
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
protected nint WindowHandle { get; set; }
public IHostUITheme HostUITheme { get; }
@ -72,7 +72,7 @@ namespace Ryujinx.Headless
protected SDL2MouseDriver MouseDriver;
private readonly InputManager _inputManager;
private readonly IKeyboard _keyboardInterface;
private readonly GraphicsDebugLevel _glLogLevel;
protected readonly GraphicsDebugLevel GlLogLevel;
private readonly Stopwatch _chrono;
private readonly long _ticksPerFrame;
private readonly CancellationTokenSource _gpuCancellationTokenSource;
@ -104,7 +104,7 @@ namespace Ryujinx.Headless
NpadManager = _inputManager.CreateNpadManager();
TouchScreenManager = _inputManager.CreateTouchScreenManager();
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
_glLogLevel = glLogLevel;
GlLogLevel = glLogLevel;
_chrono = new Stopwatch();
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
_gpuCancellationTokenSource = new CancellationTokenSource();
@ -137,7 +137,7 @@ namespace Ryujinx.Headless
private void SetWindowIcon()
{
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo");
Stream iconStream = EmbeddedResources.GetStream("Ryujinx/Assets/UIImages/Logo_Ryujinx.png");
byte[] iconBytes = new byte[iconStream!.Length];
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
@ -191,7 +191,7 @@ namespace Ryujinx.Headless
FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
}
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags());
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | WindowFlags);
if (WindowHandle == nint.Zero)
{
@ -246,7 +246,7 @@ namespace Ryujinx.Headless
protected abstract void SwapBuffers();
public abstract SDL_WindowFlags GetWindowFlags();
public abstract SDL_WindowFlags WindowFlags { get; }
private string GetGpuDriverName()
{
@ -268,7 +268,7 @@ namespace Ryujinx.Headless
{
InitializeWindowRenderer();
Device.Gpu.Renderer.Initialize(_glLogLevel);
Device.Gpu.Renderer.Initialize(GlLogLevel);
InitializeRenderer();
@ -308,21 +308,6 @@ namespace Ryujinx.Headless
if (_ticks >= _ticksPerFrame)
{
string dockedMode = Device.System.State.DockedMode ? "Docked" : "Handheld";
float scale = GraphicsConfig.ResScale;
if (scale != 1)
{
dockedMode += $" ({scale}x)";
}
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.VSyncMode.ToString(),
dockedMode,
Device.Configuration.AspectRatio.ToText(),
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
$"GPU: {_gpuDriverName}"));
_ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
}
}
@ -572,5 +557,10 @@ namespace Ryujinx.Headless
SDL2Driver.Instance.Dispose();
}
}
public UserProfile ShowPlayerSelectDialog()
{
return AccountSaveDataManager.GetLastUsedUser();
}
}
}

View File

@ -230,13 +230,16 @@ namespace Ryujinx.Ava
internal static void PrintSystemInfo()
{
Logger.Notice.Print(LogClass.Application, $"{RyujinxApp.FullAppName} Version: {Version}");
Logger.Notice.Print(LogClass.Application, $".NET Runtime: {RuntimeInformation.FrameworkDescription}");
SystemInfo.Gather().Print();
var enabledLogLevels = Logger.GetEnabledLevels().ToArray();
Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {(enabledLogLevels.Length is 0
? "<None>"
: enabledLogLevels.JoinToString(", "))}");
Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {
Logger.GetEnabledLevels()
.FormatCollection(
x => x.ToString(),
separator: ", ",
emptyCollectionFallback: "<None>")
}");
Logger.Notice.Print(LogClass.Application,
AppDataManager.Mode == AppDataManager.LaunchMode.Custom

View File

@ -123,12 +123,13 @@
<Generator>MSBuild:Compile</Generator>
</AvaloniaResource>
<AvaloniaResource Include="Assets\Styles\Styles.xaml" />
<AvaloniaResource Include="Assets\Styles\CheckboxMenuItemStyle.axaml" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\locales.json" />
<None Remove="Assets\Styles\Styles.xaml" />
<None Remove="Assets\Styles\Themes.xaml" />
<None Remove="Assets\Styles\CheckboxMenuItemStyle.xaml" />
<None Remove="Assets\Icons\Controller_JoyConLeft.svg" />
<None Remove="Assets\Icons\Controller_JoyConPair.svg" />
<None Remove="Assets\Icons\Controller_JoyConRight.svg" />
@ -150,6 +151,7 @@
</EmbeddedResource>
<EmbeddedResource Include="Assets\locales.json" />
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
<EmbeddedResource Include="Assets\Styles\CheckboxMenuItemStyle.axaml" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
@ -166,7 +168,6 @@
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Assets\locales.json" />
@ -174,4 +175,5 @@
<ItemGroup>
<Folder Include="Assets\Fonts\Mono\" />
</ItemGroup>
</Project>

View File

@ -16,5 +16,6 @@
<Application.Styles>
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
<StyleInclude Source="/Assets/Styles/CheckboxMenuItemStyle.axaml"/>
</Application.Styles>
</Application>

View File

@ -1,17 +1,24 @@
using Avalonia.Controls;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common;
using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
using Ryujinx.HLE.UI;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
namespace Ryujinx.Ava.UI.Applet
@ -253,5 +260,59 @@ namespace Ryujinx.Ava.UI.Applet
}
public IDynamicTextInputHandler CreateDynamicTextInputHandler() => new AvaloniaDynamicTextInputHandler(_parent);
public UserProfile ShowPlayerSelectDialog()
{
UserId selected = UserId.Null;
byte[] defaultGuestImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/GuestUserImage.jpg");
UserProfile guest = new UserProfile(new UserId("00000000000000000000000000000080"), "Guest", defaultGuestImage);
ManualResetEvent dialogCloseEvent = new(false);
Dispatcher.UIThread.InvokeAsync(async () =>
{
ObservableCollection<BaseModel> profiles = [];
NavigationDialogHost nav = new();
_parent.AccountManager.GetAllUsers()
.OrderBy(x => x.Name)
.ForEach(profile => profiles.Add(new Models.UserProfile(profile, nav)));
profiles.Add(new Models.UserProfile(guest, nav));
UserSelectorDialogViewModel viewModel = new()
{
Profiles = profiles,
SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
};
UserSelectorDialog content = new(viewModel);
(selected, _) = await UserSelectorDialog.ShowInputDialog(content);
dialogCloseEvent.Set();
});
dialogCloseEvent.WaitOne();
UserProfile profile = _parent.AccountManager.LastOpenedUser;
if (selected == guest.UserId)
{
profile = guest;
}
else if (selected == UserId.Null)
{
profile = null;
}
else
{
foreach (UserProfile p in _parent.AccountManager.GetAllUsers())
{
if (p.UserId == selected)
{
profile = p;
break;
}
}
}
return profile;
}
}
}

View File

@ -0,0 +1,121 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Applet.UserSelectorDialog"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
d:DesignHeight="450"
MinWidth="500"
d:DesignWidth="800"
mc:Ignorable="d"
Focusable="True"
x:DataType="viewModels:UserSelectorDialogViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Design.DataContext>
<viewModels:UserSelectorDialogViewModel />
</Design.DataContext>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
CornerRadius="5"
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
BorderThickness="1">
<ListBox
MaxHeight="300"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Background="Transparent"
ItemsSource="{Binding Profiles}"
SelectionChanged="ProfilesList_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Margin" Value="5 5 0 5" />
<Setter Property="CornerRadius" Value="5" />
</Style>
<Style Selector="Rectangle#SelectionIndicator">
<Setter Property="Opacity" Value="0" />
</Style>
</ListBox.Styles>
<ListBox.DataTemplates>
<DataTemplate
DataType="models:UserProfile">
<Grid
PointerEntered="Grid_PointerEntered"
PointerExited="Grid_OnPointerExited">
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ClipToBounds="True"
CornerRadius="5"
Background="{Binding BackgroundColor}">
<StackPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image
Width="96"
Height="96"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Image, Converter={StaticResource ByteImage}}" />
<TextBlock
HorizontalAlignment="Stretch"
MaxWidth="90"
Text="{Binding Name}"
TextAlignment="Center"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
MaxLines="2"
Margin="5" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<DataTemplate
DataType="viewModels:BaseModel">
<Panel
Height="118"
Width="96">
<Panel.Styles>
<Style Selector="Panel">
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
</Style>
</Panel.Styles>
</Panel>
</DataTemplate>
</ListBox.DataTemplates>
</ListBox>
</Border>
<StackPanel
Grid.Row="1"
Margin="0 24 0 0"
HorizontalAlignment="Left"
Orientation="Horizontal"
Spacing="10">
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,123 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
namespace Ryujinx.Ava.UI.Applet
{
public partial class UserSelectorDialog : UserControl, INotifyPropertyChanged
{
public UserSelectorDialogViewModel ViewModel { get; set; }
public UserSelectorDialog(UserSelectorDialogViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
DataContext = ViewModel;
}
private void Grid_PointerEntered(object sender, PointerEventArgs e)
{
if (sender is Grid { DataContext: UserProfile profile })
{
profile.IsPointerOver = true;
}
}
private void Grid_OnPointerExited(object sender, PointerEventArgs e)
{
if (sender is Grid { DataContext: UserProfile profile })
{
profile.IsPointerOver = false;
}
}
private void ProfilesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ListBox listBox)
{
int selectedIndex = listBox.SelectedIndex;
if (selectedIndex >= 0 && selectedIndex < ViewModel.Profiles.Count)
{
if (ViewModel.Profiles[selectedIndex] is UserProfile userProfile)
{
ViewModel.SelectedUserId = userProfile.UserId;
Logger.Info?.Print(LogClass.UI, $"Selected user: {userProfile.UserId}");
ObservableCollection<BaseModel> newProfiles = [];
foreach (var item in ViewModel.Profiles)
{
if (item is UserProfile originalItem)
{
var profile = new UserProfileSft(originalItem.UserId, originalItem.Name, originalItem.Image);
if (profile.UserId == ViewModel.SelectedUserId)
{
profile.AccountState = AccountState.Open;
}
newProfiles.Add(new UserProfile(profile, new NavigationDialogHost()));
}
}
ViewModel.Profiles = newProfiles;
}
}
}
}
public static async Task<(UserId Id, bool Result)> ShowInputDialog(UserSelectorDialog content)
{
ContentDialog contentDialog = new()
{
Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle],
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
SecondaryButtonText = string.Empty,
CloseButtonText = LocaleManager.Instance[LocaleKeys.Cancel],
Content = content,
Padding = new Thickness(0)
};
UserId result = UserId.Null;
bool input = false;
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
{
if (eventArgs.Result == ContentDialogResult.Primary)
{
if (contentDialog.Content is UserSelectorDialog view)
{
result = view.ViewModel.SelectedUserId;
input = true;
}
}
else
{
result = UserId.Null;
input = false;
}
}
contentDialog.Closed += Handler;
await ContentDialogHelper.ShowAsync(contentDialog);
return (result, input);
}
}
}

View File

@ -106,6 +106,10 @@
Click="ExtractApplicationRomFs_Click"
Header="{ext:Locale GameListContextMenuExtractDataRomFS}"
ToolTip.Tip="{ext:Locale GameListContextMenuExtractDataRomFSToolTip}" />
<MenuItem
Click="ExtractAocRomFs_Click"
Header="{ext:Locale GameListContextMenuExtractDataAocRomFS}"
ToolTip.Tip="{ext:Locale GameListContextMenuExtractDataAocRomFSToolTip}" />
<MenuItem
Click="ExtractApplicationLogo_Click"
Header="{ext:Locale GameListContextMenuExtractDataLogo}"

View File

@ -3,10 +3,13 @@ using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using LibHac;
using LibHac.Fs;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
@ -14,6 +17,7 @@ using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS;
using SkiaSharp;
using System;
@ -279,6 +283,22 @@ namespace Ryujinx.Ava.UI.Controls
viewModel.SelectedApplication.Path,
viewModel.SelectedApplication.Name);
}
public async void ExtractAocRomFs_Click(object sender, RoutedEventArgs args)
{
if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
return;
DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.IdBase, viewModel.ApplicationLibrary);
if (selectedDlc is not null)
{
await ApplicationHelper.ExtractAoc(
viewModel.StorageProvider,
selectedDlc.ContainerPath,
selectedDlc.FileName);
}
}
public async void ExtractApplicationLogo_Click(object sender, RoutedEventArgs args)
{

View File

@ -2,11 +2,10 @@
x:Class="Ryujinx.Ava.UI.Controls.ApplicationListView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
Focusable="True"

View File

@ -0,0 +1,67 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="using:Ryujinx.Ava.UI.Helpers"
xmlns:ext="using:Ryujinx.Ava.Common.Markup"
xmlns:models="using:Ryujinx.Ava.Common.Models"
xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Controls.DlcSelectView"
x:DataType="viewModels:DlcSelectViewModel">
<Grid RowDefinitions="*,Auto,*">
<TextBlock
Classes="h1"
Margin="5, -5, 0, 15"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
Text="{ext:Locale ExtractAocListHeader}" />
<ScrollViewer Grid.Row="2">
<ListBox
AutoScrollToSelectedItem="False"
SelectionMode="Single"
Background="Transparent"
SelectedItem="{Binding SelectedDlc}"
ItemsSource="{Binding Dlcs}">
<ListBox.DataTemplates>
<DataTemplate
DataType="models:DownloadableContentModel">
<Panel Margin="10" Background="Transparent">
<Grid ColumnDefinitions="*,Auto">
<Grid
Grid.Column="0" ColumnDefinitions="*,Auto">
<TextBlock
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis">
<TextBlock.Text>
<MultiBinding Converter="{x:Static helpers:DownloadableContentLabelConverter.Instance}">
<Binding Path="FileName" />
<Binding Path="IsBundled" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock
Grid.Column="1"
Margin="10, 0, 0, 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding TitleIdStr}" />
</Grid>
</Grid>
</Panel>
</DataTemplate>
</ListBox.DataTemplates>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Background" Value="Transparent" />
</Style>
</ListBox.Styles>
</ListBox>
</ScrollViewer>
</Grid>
</UserControl>

View File

@ -0,0 +1,51 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities.AppLibrary;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Controls
{
public partial class DlcSelectView : UserControl
{
public DlcSelectView()
{
InitializeComponent();
}
#nullable enable
public static async Task<DownloadableContentModel?> Show(ulong selectedTitleId, ApplicationLibrary appLibrary)
#nullable disable
{
DlcSelectViewModel viewModel = new(selectedTitleId, appLibrary);
ContentDialog contentDialog = new()
{
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.Continue],
SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty,
Content = new DlcSelectView { DataContext = viewModel }
};
Style closeButton = new(x => x.Name("CloseButton"));
closeButton.Setters.Add(new Setter(WidthProperty, 80d));
Style closeButtonParent = new(x => x.Name("CommandSpace"));
closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty,
Avalonia.Layout.HorizontalAlignment.Right));
contentDialog.Styles.Add(closeButton);
contentDialog.Styles.Add(closeButtonParent);
await ContentDialogHelper.ShowAsync(contentDialog);
return viewModel.SelectedDlc;
}
}
}

View File

@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Controls
VirtualFileSystem ownerVirtualFileSystem,
HorizonClient ownerHorizonClient)
{
var content = new NavigationDialogHost(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem, ownerHorizonClient);
NavigationDialogHost content = new(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem, ownerHorizonClient);
ContentDialog contentDialog = new()
{
Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle],

View File

@ -7,6 +7,7 @@
Title="Ryujinx - Waiting"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterOwner"
CanResize="False"
mc:Ignorable="d"
Focusable="True">
<Grid

View File

@ -0,0 +1,48 @@
using CommunityToolkit.Mvvm.Input;
using System;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Helpers
{
#nullable enable
public static class Commands
{
public static RelayCommand Create(Action action)
=> new(action);
public static RelayCommand CreateConditional(Action action, Func<bool> canExecute)
=> new(action, canExecute);
public static RelayCommand<T> Create<T>(Action<T?> action)
=> new(action);
public static RelayCommand<T> CreateConditional<T>(Action<T?> action, Predicate<T?> canExecute)
=> new(action, canExecute);
public static AsyncRelayCommand Create(Func<Task> action)
=> new(action, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand CreateConcurrent(Func<Task> action)
=> new(action, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand CreateSilentFail(Func<Task> action)
=> new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
public static AsyncRelayCommand<T> Create<T>(Func<T?, Task> action)
=> new(action, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand<T> CreateConcurrent<T>(Func<T?, Task> action)
=> new(action, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand<T> CreateSilentFail<T>(Func<T?, Task> action)
=> new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
public static AsyncRelayCommand CreateConditional(Func<Task> action, Func<bool> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand CreateConcurrentConditional(Func<Task> action, Func<bool> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand CreateSilentFailConditional(Func<Task> action, Func<bool> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
public static AsyncRelayCommand<T> CreateConditional<T>(Func<T?, Task> action, Predicate<T?> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand<T> CreateConcurrentConditional<T>(Func<T?, Task> action, Predicate<T?> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand<T> CreateSilentFailConditional<T>(Func<T?, Task> action, Predicate<T?> canExecute)
=> new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
}
}

View File

@ -22,5 +22,22 @@ namespace Ryujinx.Ava.UI.Models
FifoStatus = fifoStatus;
ShaderCount = shaderCount;
}
public override bool Equals(object obj)
{
if (obj is not StatusUpdatedEventArgs suea) return false;
return
VSyncMode == suea.VSyncMode &&
VolumeStatus == suea.VolumeStatus &&
DockedMode == suea.DockedMode &&
AspectRatio == suea.AspectRatio &&
GameStatus == suea.GameStatus &&
FifoStatus == suea.FifoStatus &&
ShaderCount == suea.ShaderCount;
}
public override int GetHashCode()
=> HashCode.Combine(VSyncMode, VolumeStatus, AspectRatio, DockedMode, FifoStatus, GameStatus, ShaderCount);
}
}

View File

@ -27,7 +27,7 @@ namespace Ryujinx.Ava.UI.ViewModels
ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
}
private void ThemeManager_ThemeChanged(object sender, EventArgs e)
private void ThemeManager_ThemeChanged()
{
Dispatcher.UIThread.Post(() => UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value));
}

View File

@ -0,0 +1,25 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Utilities.AppLibrary;
using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels
{
public partial class DlcSelectViewModel : BaseModel
{
[ObservableProperty] private DownloadableContentModel[] _dlcs;
#nullable enable
[ObservableProperty] private DownloadableContentModel? _selectedDlc;
#nullable disable
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
{
_dlcs = appLibrary.DownloadableContents.Items
.Where(x => x.Dlc.TitleIdBase == titleId)
.Select(x => x.Dlc)
.OrderBy(it => it.IsBundled ? 0 : 1)
.ThenBy(it => it.TitleId)
.ToArray();
}
}
}

View File

@ -38,7 +38,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.HLE.UI;
using Ryujinx.Input.HLE;
using Silk.NET.Vulkan;
using SkiaSharp;
using System;
using System.Collections.Generic;
@ -489,6 +488,19 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public bool StartGamesWithoutUI
{
get => ConfigurationState.Instance.UI.StartNoUI;
set
{
ConfigurationState.Instance.UI.StartNoUI.Value = value;
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
OnPropertyChanged();
}
}
public bool ShowConsole
{
get => ConfigurationState.Instance.UI.ShowConsole;
@ -625,6 +637,7 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize],
ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListHeaderPath],
ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite],
ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel],
_ => string.Empty,
};
}
@ -695,6 +708,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public IHostUIHandler UiHandler { get; internal set; }
public bool IsSortedByFavorite => SortMode == ApplicationSort.Favorite;
public bool IsSortedByTitle => SortMode == ApplicationSort.Title;
public bool IsSortedByTitleId => SortMode == ApplicationSort.TitleId;
public bool IsSortedByDeveloper => SortMode == ApplicationSort.Developer;
public bool IsSortedByLastPlayed => SortMode == ApplicationSort.LastPlayed;
public bool IsSortedByTimePlayed => SortMode == ApplicationSort.TotalTimePlayed;
@ -727,6 +741,7 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationSort.FileSize => CreateComparer(IsAscending, app => app.FileSize),
ApplicationSort.Path => CreateComparer(IsAscending, app => app.Path),
ApplicationSort.Favorite => CreateComparer(IsAscending, app => new AppListFavoriteComparable(app)),
ApplicationSort.TitleId => CreateComparer(IsAscending, app => app.Id),
_ => null,
#pragma warning restore IDE0055
};
@ -1196,6 +1211,11 @@ namespace Ryujinx.Ava.UI.ViewModels
StartGamesInFullscreen = !StartGamesInFullscreen;
}
public void ToggleStartGamesWithoutUI()
{
StartGamesWithoutUI = !StartGamesWithoutUI;
}
public void ToggleShowConsole()
{
ShowConsole = !ShowConsole;
@ -1642,10 +1662,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task OpenAmiiboWindow()
{
if (!IsAmiiboRequested)
return;
if (AppHost.Device.System.SearchingForAmiibo(out int deviceId))
if (AppHost.Device.System.SearchingForAmiibo(out int deviceId) && IsGameRunning)
{
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
@ -1663,10 +1680,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
public async Task OpenBinFile()
{
if (!IsAmiiboRequested)
return;
if (AppHost.Device.System.SearchingForAmiibo(out int deviceId))
if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning)
{
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{

View File

@ -0,0 +1,14 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System.Collections.ObjectModel;
namespace Ryujinx.Ava.UI.ViewModels
{
public partial class UserSelectorDialogViewModel : BaseModel
{
[ObservableProperty] private UserId _selectedUserId;
[ObservableProperty] private ObservableCollection<BaseModel> _profiles = [];
}
}

View File

@ -81,25 +81,16 @@
<MenuItem
Command="{Binding ToggleFullscreen}"
Header="{ext:Locale MenuBarOptionsToggleFullscreen}"
Classes="withCheckbox"
Padding="0"
Icon="{ext:Icon fa-solid fa-expand}"
InputGesture="F11">
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
</MenuItem>
<MenuItem
Padding="0"
Command="{Binding ToggleStartGamesInFullscreen}"
Header="{ext:Locale MenuBarOptionsStartGamesInFullscreen}">
Header="{ext:Locale MenuBarOptionsStartGamesInFullscreen}"
Classes="withCheckbox">
<MenuItem.Icon>
<CheckBox
MinWidth="{DynamicResource CheckBoxSize}"
@ -107,23 +98,26 @@
IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}"
Padding="0" />
</MenuItem.Icon>
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
</MenuItem>
<MenuItem
Padding="0"
Command="{Binding ToggleStartGamesWithoutUI}"
Header="{ext:Locale MenuBarOptionsStartGamesWithoutUI}"
Classes="withCheckbox">
<MenuItem.Icon>
<CheckBox
MinWidth="{DynamicResource CheckBoxSize}"
MinHeight="{DynamicResource CheckBoxSize}"
IsChecked="{Binding StartGamesWithoutUI, Mode=TwoWay}"
Padding="0" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Padding="0"
IsVisible="{Binding ShowConsoleVisible}"
Command="{Binding ToggleShowConsole}"
Header="{ext:Locale MenuBarOptionsShowConsole}">
Header="{ext:Locale MenuBarOptionsShowConsole}"
Classes="withCheckbox">
<MenuItem.Icon>
<CheckBox
MinWidth="{DynamicResource CheckBoxSize}"
@ -131,35 +125,14 @@
IsChecked="{Binding ShowConsole, Mode=TwoWay}"
Padding="0" />
</MenuItem.Icon>
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
</MenuItem>
<Separator/>
<MenuItem
Name="ChangeLanguageMenuItem"
Padding="0"
Header="{ext:Locale MenuBarOptionsChangeLanguage}"
Icon="{ext:Icon fa-solid fa-language}">
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
Icon="{ext:Icon fa-solid fa-language}"
Classes="withCheckbox">
</MenuItem>
<MenuItem
Name="ToggleFileTypesMenuItem"
@ -171,18 +144,8 @@
Padding="0"
Header="{ext:Locale MenuBarOptionsSettings}"
Icon="{ext:Icon fa-solid fa-gear}"
ToolTip.Tip="{ext:Locale OpenSettingsTooltip}">
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
ToolTip.Tip="{ext:Locale OpenSettingsTooltip}"
Classes="withCheckbox">
</MenuItem>
<MenuItem
Command="{Binding ManageProfiles}"
@ -190,25 +153,15 @@
Header="{ext:Locale MenuBarOptionsManageUserProfiles}"
Icon="{ext:Icon mdi-account}"
IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale OpenProfileManagerTooltip}">
<MenuItem.Styles>
<Style Selector="Viewbox#PART_IconPresenter">
<Setter Property="MaxHeight" Value="36" />
<Setter Property="MinHeight" Value="36" />
<Setter Property="MaxWidth" Value="36" />
<Setter Property="MinWidth" Value="36" />
</Style>
<Style Selector="ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="-10,0,0,0" />
</Style>
</MenuItem.Styles>
ToolTip.Tip="{ext:Locale OpenProfileManagerTooltip}"
Classes="withCheckbox">
</MenuItem>
</MenuItem>
<MenuItem
Name="ActionsMenuItem"
VerticalAlignment="Center"
Header="{ext:Locale MenuBarActions}"
IsEnabled="{Binding IsGameRunning}">
IsVisible="{Binding !EnableNonGameRunningControls}">
<MenuItem
Name="PauseEmulationMenuItem"
Header="{ext:Locale MenuBarOptionsPauseEmulation}"
@ -265,21 +218,21 @@
Icon="{ext:Icon fa-solid fa-code}"
IsEnabled="{Binding IsGameRunning}" />
</MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarTools}">
<MenuItem Header="{ext:Locale MenuBarToolsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}" IsEnabled="{Binding EnableNonGameRunningControls}">
<MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFolder}" Icon="{ext:Icon mdi-folder-cog}" />
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarActions}" IsVisible="{Binding EnableNonGameRunningControls}">
<MenuItem Header="{ext:Locale MenuBarActionsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}">
<MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFolder}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem>
<MenuItem Header="{ext:Locale MenuBarToolsInstallFirmware}" Icon="{ext:Icon fa-solid fa-download}" IsEnabled="{Binding EnableNonGameRunningControls}">
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" />
<MenuItem Header="{ext:Locale MenuBarActionsInstallFirmware}" Icon="{ext:Icon fa-solid fa-download}">
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem>
<MenuItem Header="{ext:Locale MenuBarToolsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}">
<MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarToolsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" />
<MenuItem Name="UninstallFileTypesMenuItem" Header="{ext:Locale MenuBarToolsUninstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered}" />
<MenuItem Header="{ext:Locale MenuBarActionsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}">
<MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" />
<MenuItem Name="UninstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsUninstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered}" />
</MenuItem>
<Separator />
<MenuItem Name="XciTrimmerMenuItem" Header="{ext:Locale MenuBarToolsXCITrimmer}" IsEnabled="{Binding EnableNonGameRunningControls}" Icon="{ext:Icon fa-solid fa-scissors}" />
<MenuItem Name="XciTrimmerMenuItem" Header="{ext:Locale MenuBarActionsXCITrimmer}" Icon="{ext:Icon fa-solid fa-scissors}" />
</MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}">
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}">

View File

@ -37,20 +37,20 @@ namespace Ryujinx.Ava.UI.Views.Main
ToggleFileTypesMenuItem.ItemsSource = GenerateToggleFileTypeItems();
ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems();
MiiAppletMenuItem.Command = new AsyncRelayCommand(OpenMiiApplet);
CloseRyujinxMenuItem.Command = new RelayCommand(CloseWindow);
OpenSettingsMenuItem.Command = new AsyncRelayCommand(OpenSettings);
PauseEmulationMenuItem.Command = new RelayCommand(() => ViewModel.AppHost?.Pause());
ResumeEmulationMenuItem.Command = new RelayCommand(() => ViewModel.AppHost?.Resume());
StopEmulationMenuItem.Command = new AsyncRelayCommand(() => ViewModel.AppHost?.ShowExitPrompt().OrCompleted());
CheatManagerMenuItem.Command = new AsyncRelayCommand(OpenCheatManagerForCurrentApp);
InstallFileTypesMenuItem.Command = new AsyncRelayCommand(InstallFileTypes);
UninstallFileTypesMenuItem.Command = new AsyncRelayCommand(UninstallFileTypes);
XciTrimmerMenuItem.Command = new AsyncRelayCommand(() => XCITrimmerWindow.Show(ViewModel));
AboutWindowMenuItem.Command = new AsyncRelayCommand(AboutWindow.Show);
CompatibilityListMenuItem.Command = new AsyncRelayCommand(CompatibilityList.Show);
MiiAppletMenuItem.Command = Commands.Create(OpenMiiApplet);
CloseRyujinxMenuItem.Command = Commands.Create(CloseWindow);
OpenSettingsMenuItem.Command = Commands.Create(OpenSettings);
PauseEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.Pause());
ResumeEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.Resume());
StopEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.ShowExitPrompt().OrCompleted());
CheatManagerMenuItem.Command = Commands.CreateSilentFail(OpenCheatManagerForCurrentApp);
InstallFileTypesMenuItem.Command = Commands.Create(InstallFileTypes);
UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes);
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show);
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show);
CompatibilityListMenuItem.Command = Commands.Create(CompatibilityList.Show);
UpdateMenuItem.Command = new AsyncRelayCommand(async () =>
UpdateMenuItem.Command = Commands.Create(async () =>
{
if (Updater.CanUpdate(true))
await Updater.BeginUpdateAsync(true);
@ -58,12 +58,12 @@ namespace Ryujinx.Ava.UI.Views.Main
FaqMenuItem.Command =
SetupGuideMenuItem.Command =
LdnGuideMenuItem.Command = new RelayCommand<string>(OpenHelper.OpenUrl);
LdnGuideMenuItem.Command = Commands.Create<string>(OpenHelper.OpenUrl);
WindowSize720PMenuItem.Command =
WindowSize1080PMenuItem.Command =
WindowSize1440PMenuItem.Command =
WindowSize2160PMenuItem.Command = new RelayCommand<string>(ChangeWindowSize);
WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize);
}
private IEnumerable<CheckBox> GenerateToggleFileTypeItems() =>
@ -138,14 +138,14 @@ namespace Ryujinx.Ava.UI.Views.Main
ViewModel.LoadConfigurableHotKeys();
}
public static readonly AppletMetadata MiiApplet = new("miiEdit", 0x0100000000001009);
public AppletMetadata MiiApplet => new(ViewModel.ContentManager, "miiEdit", 0x0100000000001009);
public async Task OpenMiiApplet()
{
if (MiiApplet.CanStart(ViewModel.ContentManager, out var appData, out var nacpData))
{
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
}
if (!MiiApplet.CanStart(out var appData, out var nacpData))
return;
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
}
public async Task OpenCheatManagerForCurrentApp()

View File

@ -105,6 +105,12 @@
GroupName="Sort"
IsChecked="{Binding IsSortedByTitle, Mode=OneTime}"
Tag="Title" />
<RadioButton
Checked="Sort_Checked"
Content="{ext:Locale DlcManagerTableHeadingTitleIdLabel}"
GroupName="Sort"
IsChecked="{Binding IsSortedByTitleId, Mode=OneTime}"
Tag="TitleId" />
<RadioButton
Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderDeveloper}"

View File

@ -29,7 +29,7 @@
<TextBlock
Foreground="{DynamicResource SecondaryTextColor}"
TextDecorations="Underline"
Text="Game-specific hacks &amp; tricks to alleviate performance issues or crashing. Will cause issues." />
Text="Highly specific hacks &amp; tricks to alleviate performance issues, crashing, or freezing. Will cause issues." />
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal"

View File

@ -136,6 +136,12 @@
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel

View File

@ -114,8 +114,7 @@
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddGameDirTooltip}"
Click="AddGameDirButton_OnClick">
ToolTip.Tip="{ext:Locale AddGameDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>
@ -168,8 +167,7 @@
Grid.Column="1"
MinWidth="90"
Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}"
Click="AddAutoloadDirButton_OnClick">
ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}">
<TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button>

View File

@ -1,12 +1,17 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using Avalonia.VisualTree;
using Gommon;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Settings
{
@ -18,31 +23,39 @@ namespace Ryujinx.Ava.UI.Views.Settings
{
InitializeComponent();
ShowTitleBarBox.IsVisible = OperatingSystem.IsWindows();
AddGameDirButton.Command =
Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories, true));
AddAutoloadDirButton.Command =
Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories, false));
}
private async void AddGameDirButton_OnClick(object sender, RoutedEventArgs e)
private async Task AddDirButton(TextBox addDirBox, AvaloniaList<string> directories, bool isGameList)
{
string path = GameDirPathBox.Text;
string path = addDirBox.Text;
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path))
{
ViewModel.GameDirectories.Add(path);
ViewModel.GameDirectoryChanged = true;
directories.Add(path);
addDirBox.Clear();
if (isGameList)
ViewModel.GameDirectoryChanged = true;
else
ViewModel.AutoloadDirectoryChanged = true;
}
else
{
if (this.GetVisualRoot() is Window window)
{
var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});
Optional<IStorageFolder> folder = await RyujinxApp.MainWindow.ViewModel.StorageProvider.OpenSingleFolderPickerAsync();
if (result.Count > 0)
{
ViewModel.GameDirectories.Add(result[0].Path.LocalPath);
if (folder.HasValue)
{
directories.Add(folder.Value.Path.LocalPath);
if (isGameList)
ViewModel.GameDirectoryChanged = true;
}
else
ViewModel.AutoloadDirectoryChanged = true;
}
}
}
@ -63,33 +76,6 @@ namespace Ryujinx.Ava.UI.Views.Settings
}
}
private async void AddAutoloadDirButton_OnClick(object sender, RoutedEventArgs e)
{
string path = AutoloadDirPathBox.Text;
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.AutoloadDirectories.Contains(path))
{
ViewModel.AutoloadDirectories.Add(path);
ViewModel.AutoloadDirectoryChanged = true;
}
else
{
if (this.GetVisualRoot() is Window window)
{
var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});
if (result.Count > 0)
{
ViewModel.AutoloadDirectories.Add(result[0].Path.LocalPath);
ViewModel.AutoloadDirectoryChanged = true;
}
}
}
}
private void RemoveAutoloadDirButton_OnClick(object sender, RoutedEventArgs e)
{
int oldIndex = AutoloadDirsList.SelectedIndex;

View File

@ -14,9 +14,6 @@
mc:Ignorable="d"
x:DataType="viewModels:DownloadableContentManagerViewModel"
Focusable="True">
<UserControl.Resources>
<helpers:DownloadableContentLabelConverter x:Key="DownloadableContentLabel" />
</UserControl.Resources>
<Grid RowDefinitions="Auto,Auto,*,Auto">
<StackPanel
Grid.Row="0"
@ -89,7 +86,7 @@
<ListBox.DataTemplates>
<DataTemplate
DataType="models:DownloadableContentModel">
<Panel Margin="10">
<Panel Margin="10" Background="Transparent">
<Grid ColumnDefinitions="*,Auto">
<Grid
Grid.Column="0" ColumnDefinitions="*,Auto">
@ -101,7 +98,7 @@
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource DownloadableContentLabel}">
<MultiBinding Converter="{x:Static helpers:DownloadableContentLabelConverter.Instance}">
<Binding Path="FileName" />
<Binding Path="IsBundled" />
</MultiBinding>
@ -112,7 +109,7 @@
Margin="10 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding TitleId}" />
Text="{Binding TitleIdStr}" />
</Grid>
<StackPanel
Grid.Column="1"

View File

@ -2,6 +2,8 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.ViewModels;

View File

@ -32,6 +32,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
@ -136,6 +137,8 @@ namespace Ryujinx.Ava.UI.Windows
base.OnApplyTemplate(e);
NotificationHelper.SetNotificationManager(this);
Executor.ExecuteBackgroundAsync(ShowIntelMacWarningAsync);
}
private void OnScalingChanged(object sender, EventArgs e)
@ -688,6 +691,7 @@ namespace Ryujinx.Ava.UI.Windows
ApplicationLibrary.LoadApplications(ConfigurationState.Instance.UI.GameDirs);
var autoloadDirs = ConfigurationState.Instance.UI.AutoloadDirs.Value;
autoloadDirs.ForEach(dir => Logger.Info?.Print(LogClass.Application, $"Auto loading DLC & updates from: {dir}"));
if (autoloadDirs.Count > 0)
{
var updatesLoaded = ApplicationLibrary.AutoLoadTitleUpdates(autoloadDirs, out int updatesRemoved);
@ -731,5 +735,20 @@ namespace Ryujinx.Ava.UI.Windows
(int)Symbol.Checkmark);
});
}
private static bool _intelMacWarningShown = !(OperatingSystem.IsMacOS() &&
(RuntimeInformation.OSArchitecture == Architecture.X64 ||
RuntimeInformation.OSArchitecture == Architecture.X86));
public static async Task ShowIntelMacWarningAsync()
{
if (_intelMacWarningShown) return;
await Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.CreateWarningDialog(
"Intel Mac Warning",
"Intel Macs are not supported and will not work properly.\nIf you continue, do not come to our Discord asking for support;\nand do not report bugs on the GitHub. They will be closed."));
_intelMacWarningShown = true;
}
}
}

View File

@ -28,15 +28,15 @@ namespace Ryujinx.Ava.UI.Windows
InitializeComponent();
}
public static async Task Show(MainWindowViewModel mainWindowViewModel)
public static async Task Show()
{
ContentDialog contentDialog = new()
{
PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty,
Content = new XCITrimmerWindow(mainWindowViewModel),
Title = string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle]),
Content = new XCITrimmerWindow(RyujinxApp.MainWindow.ViewModel),
Title = LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle]
};
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());

View File

@ -87,6 +87,8 @@ namespace Ryujinx.Ava
return;
}
Logger.Info?.Print(LogClass.Application, "Checking for updates.");
// Get latest version number from GitHub API
try
@ -140,6 +142,8 @@ namespace Ryujinx.Ava
OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion));
}
}
Logger.Info?.Print(LogClass.Application, "Up to date.");
_running = false;
@ -214,6 +218,8 @@ namespace Ryujinx.Ava
? $"Canary {currentVersion} -> Canary {newVersion}"
: $"{currentVersion} -> {newVersion}";
Logger.Info?.Print(LogClass.Application, $"Version found: {newVersionString}");
RequestUserToUpdate:
// Show a message asking the user if they want to update
UserResult shouldUpdate = await ContentDialogHelper.CreateUpdaterChoiceDialog(

View File

@ -840,7 +840,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
try
{
// Remove any downloadable content which can no longer be located on disk
Logger.Notice.Print(LogClass.Application, $"Removing non-existing Title DLCs");
var dlcToRemove = _downloadableContents.Items
.Where(dlc => !File.Exists(dlc.Dlc.ContainerPath))
.ToList();
@ -852,8 +851,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
foreach (string appDir in appDirs)
{
Logger.Notice.Print(LogClass.Application, $"Auto loading DLC from: {appDir}");
if (_cancellationToken.Token.IsCancellationRequested)
{
return newDlcLoaded;
@ -956,7 +953,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
var titleIdsToRefresh = new HashSet<ulong>();
// Remove any updates which can no longer be located on disk
Logger.Notice.Print(LogClass.Application, $"Removing non-existing Title Updates");
var updatesToRemove = _titleUpdates.Items
.Where(it => !File.Exists(it.TitleUpdate.Path))
.ToList();
@ -971,8 +967,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
foreach (string appDir in appDirs)
{
Logger.Notice.Print(LogClass.Application, $"Auto loading updates from: {appDir}");
if (_cancellationToken.Token.IsCancellationRequested)
{
return numUpdatesLoaded;

View File

@ -54,5 +54,9 @@ namespace Ryujinx.Ava.Utilities
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
public bool CanStart(out ApplicationData appData,
out BlitStruct<ApplicationControlProperty> appControl)
=> CanStart(null, out appData, out appControl);
}
}

View File

@ -28,7 +28,9 @@ namespace Ryujinx.Ava.Utilities.Compat
public class CompatibilityCsv
{
static CompatibilityCsv()
static CompatibilityCsv() => Load();
public static void Load()
{
using Stream csvStream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("RyujinxGameCompatibilityList")!;
@ -37,15 +39,31 @@ namespace Ryujinx.Ava.Utilities.Compat
using SepReader reader = Sep.Reader().From(csvStream);
ColumnIndices columnIndices = new(reader.Header.IndexOf);
Entries = reader
_entries = reader
.Enumerate(row => new CompatibilityEntry(ref columnIndices, row))
.OrderBy(it => it.GameName)
.ToArray();
Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.", "LoadCompatCsv");
Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.", "LoadCompatibility");
}
public static CompatibilityEntry[] Entries { get; private set; }
public static void Unload()
{
_entries = null;
}
private static CompatibilityEntry[] _entries;
public static CompatibilityEntry[] Entries
{
get
{
if (_entries == null)
Load();
return _entries;
}
}
}
public class CompatibilityEntry

View File

@ -1,11 +1,8 @@
using Avalonia.Controls;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using nietras.SeparatedValues;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Utilities.Compat
@ -35,6 +32,8 @@ namespace Ryujinx.Ava.Utilities.Compat
contentDialog.Styles.Add(closeButtonParent);
await ContentDialogHelper.ShowAsync(contentDialog);
CompatibilityCsv.Unload();
}
public CompatibilityList()

View File

@ -1,19 +1,18 @@
using CommunityToolkit.Mvvm.ComponentModel;
using ExCSS;
using Gommon;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities.AppLibrary;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Ava.Utilities.Compat
{
public partial class CompatibilityViewModel : ObservableObject
public class CompatibilityViewModel : BaseModel
{
[ObservableProperty] private bool _onlyShowOwnedGames = true;
private bool _onlyShowOwnedGames = true;
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Entries;
private readonly string[] _ownedGameTitleIds = [];
private readonly ApplicationLibrary _appLibrary;
private string[] _ownedGameTitleIds = [];
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
? _currentEntries.Where(x =>
@ -24,14 +23,23 @@ namespace Ryujinx.Ava.Utilities.Compat
public CompatibilityViewModel(ApplicationLibrary appLibrary)
{
_appLibrary = appLibrary;
appLibrary.ApplicationCountUpdated += (_, _)
=> _ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
_ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
}
PropertyChanged += (_, args) =>
public bool OnlyShowOwnedGames
{
get => _onlyShowOwnedGames;
set
{
if (args.PropertyName is nameof(OnlyShowOwnedGames))
OnPropertyChanged(nameof(CurrentEntries));
};
OnPropertyChanging();
OnPropertyChanging(nameof(CurrentEntries));
_onlyShowOwnedGames = value;
OnPropertyChanged();
OnPropertyChanged(nameof(CurrentEntries));
}
}
public void Search(string searchTerm)

View File

@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
public const int CurrentVersion = 59;
public const int CurrentVersion = 60;
/// <summary>
/// Version of the configuration file format
@ -351,6 +351,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary>
public bool StartFullscreen { get; set; }
/// <summary>
/// Start games with UI hidden
/// </summary>
public bool StartNoUI { get; set; }
/// <summary>
/// Show console window
/// </summary>

View File

@ -127,6 +127,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
UI.GridSize.Value = cff.GridSize;
UI.ApplicationSort.Value = cff.ApplicationSort;
UI.StartFullscreen.Value = cff.StartFullscreen;
UI.StartNoUI.Value = cff.StartNoUI;
UI.ShowConsole.Value = cff.ShowConsole;
UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
@ -414,7 +415,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
// This was accidentally enabled by default when it was PRed. That is not what we want,
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
cff.IgnoreApplet = false;
})
}),
(60, static cff => cff.StartNoUI = false)
);
}
}

View File

@ -152,6 +152,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary>
public ReactiveObject<bool> StartFullscreen { get; private set; }
/// <summary>
/// Start games with UI hidden
/// </summary>
public ReactiveObject<bool> StartNoUI { get; private set; }
/// <summary>
/// Hide / Show Console Window
/// </summary>
@ -192,6 +197,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
WindowStartup = new WindowStartupSettings();
BaseStyle = new ReactiveObject<string>();
StartFullscreen = new ReactiveObject<bool>();
StartNoUI = new ReactiveObject<bool>();
GameListViewMode = new ReactiveObject<int>();
ShowNames = new ReactiveObject<bool>();
GridSize = new ReactiveObject<int>();

View File

@ -125,6 +125,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
ApplicationSort = UI.ApplicationSort,
IsAscendingOrder = UI.IsAscendingOrder,
StartFullscreen = UI.StartFullscreen,
StartNoUI = UI.StartNoUI,
ShowConsole = UI.ShowConsole,
EnableKeyboard = Hid.EnableKeyboard,
EnableMouse = Hid.EnableMouse,
@ -233,6 +234,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
UI.ApplicationSort.Value = 0;
UI.IsAscendingOrder.Value = true;
UI.StartFullscreen.Value = false;
UI.StartNoUI.Value = false;
UI.ShowConsole.Value = true;
UI.WindowStartup.WindowSizeWidth.Value = 1280;
UI.WindowStartup.WindowSizeHeight.Value = 760;

View File

@ -0,0 +1,47 @@
using Avalonia.Platform.Storage;
using Gommon;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Utilities
{
public static class StorageProviderExtensions
{
public static async Task<Optional<IStorageFolder>> OpenSingleFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false))
.Then(folders => folders.FindFirst());
public static async Task<Optional<IStorageFile>> OpenSingleFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false))
.Then(files => files.FindFirst());
public static async Task<Optional<IReadOnlyList<IStorageFolder>>> OpenMultiFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true))
.Then(folders => folders.Count > 0 ? Optional.Of(folders) : default);
public static async Task<Optional<IReadOnlyList<IStorageFile>>> OpenMultiFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true))
.Then(files => files.Count > 0 ? Optional.Of(files) : default);
private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FilePickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
private static FolderPickerOpenOptions FixOpenOptions(this FolderPickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FolderPickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
}
}

View File

@ -4,7 +4,7 @@ namespace Ryujinx.Ava.Utilities
{
public static class TitleHelper
{
public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, string pauseString = "")
public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, bool customTitlebar, string pauseString = "")
{
if (activeProcess == null)
return string.Empty;
@ -14,7 +14,9 @@ namespace Ryujinx.Ava.Utilities
string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
string appTitle = $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
string appTitle = customTitlebar
? $"Ryujinx {applicationVersion}\n{titleNameSection.Trim()}\n{titleVersionSection.Trim()}\n{titleIdSection.Trim()}{titleArchSection}"
: $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
return !string.IsNullOrEmpty(pauseString)
? appTitle + $" ({pauseString})"