Compare commits

..

22 Commits

Author SHA1 Message Date
Goodfeat
6f59a14ec6 Small Fix: now it is enough to activate dirty hack in global settings for the option...
See merge request [ryubing/ryujinx!20](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/20)
2025-05-23 06:27:33 -05:00
GreemDev
d85ec0eff5 infra: use src.ryujinx.app redirect domain for git repo button 2025-05-20 04:40:46 -05:00
GreemDev
02ad827a94 chore: Remove mention of GitHub in changelog button tooltip 2025-05-20 04:39:36 -05:00
GreemDev
6e7220eb28 chore: specify Nintendo Switch 1 in about window and remove leftover mention of GitHub 2025-05-20 04:37:03 -05:00
GreemDev
7a3a21b0c0 ui: Proper light/dark GitLab logos.
Images from 6c7b7d6fc4
2025-05-20 04:36:31 -05:00
GreemDev
92440afcd7 UI: Show Total Time Played at the bottom of the UI in the status bar next to game total.
Does not show up in-game, and is recalculated every time the game list is reloaded.
2025-05-20 04:19:54 -05:00
GreemDev
df3b5b4bd8 gpu: tweak: Do not log missing Votevtg implementation. 2025-05-20 03:28:03 -05:00
GreemDev
11cc80f7fc infra: Generate .nupkg when building ARMeilleure, Ryujinx.Common, and Ryujinx.Memory.
Additionally added a script to push them to Ryubing GitLab package registry. This script is my use only since it assumes you have the necessary authentication locally & on the server.

TODO: figure out a way to get proper versioning for them.
2025-05-18 03:10:38 -05:00
GreemDev
f6c1e97110 infra: Update to Ryujinx.LibHac 0.20.0.
This time it's pulled in via GitLab package registry.
2025-05-18 02:26:39 -05:00
GreemDev
e18e27fbc5 Revert "infra: Update LibHac to v0.20.0."
This seems to have broken some mods.

This reverts commit 1d4928e859.
2025-05-14 21:36:02 -05:00
GreemDev
f1eb911d25 Revert "hle: fix: TargetInvocationException when initializing IParentalControlService"
This reverts commit e1c0b3acab.
2025-05-14 21:35:19 -05:00
GreemDev
e1c0b3acab hle: fix: TargetInvocationException when initializing IParentalControlService
The original implementation was a little overengineered (and didn't work). I suppose the games I tested simply didn't init the service.
2025-05-14 18:10:54 -05:00
GreemDev
1d4928e859 infra: Update LibHac to v0.20.0.
See merge request [ryubing/ryujinx!33](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/33)
2025-05-14 15:52:14 -05:00
KeatonTheBot
28b8dc14c7 Vulkan: Restrict feedback loop detection to AMD RDNA 3 GPUs
See merge request [ryubing/ryujinx!25](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/25)
2025-05-13 19:27:24 -05:00
GreemDev
21971a2be7 infra: Switch to [Ryujinx.LibHac](https://git.ryujinx.app/ryubing/libhac)
The original repository disappeared a few days ago, and we had a backup.
2025-05-13 00:33:27 -05:00
WilliamWsyHK
321bdecbc2 Typo for "Verification"
See merge request [ryubing/ryujinx!32](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/32)
2025-05-11 12:47:54 -05:00
GreemDev
6904d6a461 fix: Prevent loading the Switch Verification homebrew specifically.
Its intended purpose is to be installed on a modded real Switch. It is wholly useless and pointless to use it in the emulator, and this will give those users a hint they might be doing something incorrectly.
2025-05-04 03:26:54 -05:00
Hack茶ん
d8e3ab3974 Update Korean translation
See merge request [ryubing/ryujinx!30](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/30)
2025-04-28 23:29:41 -05:00
LotP
9b429afbb4 fix: PPTC blacklist trigger conditions
See merge request ryubing/ryujinx!28
2025-04-27 16:57:57 -05:00
GreemDev
b71a4cb745 docs: compat: Breakout Beyond & Nikoderiko: The Magical World 2025-04-26 19:14:08 -05:00
shinyoyo
844b1d8b9a Update Simplified Chinese translation.
See merge request ryubing/ryujinx!27
2025-04-25 21:03:27 -05:00
LotP
c4ea0e0df2 Reset PPTC Carriers on invalidation
See merge request ryubing/ryujinx!26
2025-04-24 12:48:22 -05:00
46 changed files with 297 additions and 122 deletions

19
BuildAndPushLibraries.sh Normal file
View File

@@ -0,0 +1,19 @@
function pub {
dotnet publish -c release
}
function package {
cd src/$1
pub
mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg
cd ../../
}
rm -rf pkgs
mkdir pkgs
package ARMeilleure
package Ryujinx.Common
package Ryujinx.Memory
dotnet nuget push pkgs/*.nupkg --source RyubingPkgs

View File

@@ -23,7 +23,6 @@
<PackageVersion Include="DynamicData" Version="9.0.4" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="Humanizer" Version="2.14.1" />
<PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
@@ -41,6 +40,7 @@
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.20.0-alpha.103" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.1.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />

View File

@@ -1947,6 +1947,31 @@
"zh_TW": "LDN 上在線的玩家數量: {0}"
}
},
{
"ID": "GameListLabelTotalTimePlayed",
"Translations": {
"ar_SA": "",
"de_DE": "Gesamte Spielzeit: {0}",
"el_GR": "Συνολικός χρόνος παιχνιδιού: {0}",
"en_US": "Total Play Time: {0}",
"es_ES": "Tiempo total de juego: {0}",
"fr_FR": "Temps de jeu total: {0}",
"he_IL": "",
"it_IT": "Tempo totale di gioco: {0}",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "Całkowity czas gry: {0}",
"pt_BR": "Tempo total de jogo: {0}",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "Toplam Oyun Süresi: {0}",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "GameListContextMenuOpenUserSaveDirectory",
"Translations": {
@@ -5393,7 +5418,7 @@
"th_TH": "ข้ามหน้าต่างโต้ตอบ 'จัดการโปรไฟล์ผู้ใช้งาน'",
"tr_TR": "'Kullanıcı Profillerini Yönet' iletişim kutusunu atla",
"uk_UA": "Пропустити діалог 'Керувати профілями користувачів'",
"zh_CN": "跳过对话框“管理用户账户”",
"zh_CN": "跳过 “管理用户账户” 对话框",
"zh_TW": "略過對話框「管理使用者設定檔」"
}
},
@@ -7034,7 +7059,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"ko_KR": "발견된 구성 :\n\n이름 : \t{0}\n가이드 : \t{1}\n\n 컨트롤러 연결 대기 중...",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -7043,7 +7068,7 @@
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_CN": "发现配置:\n\n名称:\t{0}\nGUID:\t{1}\n\n 正在等待控制器连接...",
"zh_TW": ""
}
},
@@ -7393,7 +7418,7 @@
"th_TH": "การควบคุมได้รับการตั้งค่าแล้ว\n\nกำลังรอการเชื่อมต่อคอนโทรลเลอร์...",
"tr_TR": "Kontrol yapılandırıldı.\n\nKontrolcü bağlantısı bekleniyor...",
"uk_UA": "Керування налаштовано.\n\nОчікується підключення контролера...",
"zh_CN": "控制已配置。\n\n等待控制器连接...",
"zh_CN": "已配置控制器。\n\n正在等待控制器连接...",
"zh_TW": "控制已設定。\n\n等待控制器連接..."
}
},
@@ -7418,7 +7443,7 @@
"th_TH": "ยกเลิกการเชื่อมโยง",
"tr_TR": "Bağlantıyı Kes",
"uk_UA": "Відв'язати",
"zh_CN": "解除绑定",
"zh_CN": "取消绑定",
"zh_TW": "解除綁定"
}
},
@@ -15503,23 +15528,23 @@
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
"en_US": "Ryujinx is an emulator for the Nintendo Switch™ 1.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitLab or Discord.",
"es_ES": "",
"fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™.\nObtenez le dernières nouvelles sur le Discord.\nLes développeurs qui veulent contribuer peuvent en savoir plus sur notre GitHub ou Discord.",
"fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™ 1.\nObtenez le dernières nouvelles sur le Discord.\nLes développeurs qui veulent contribuer peuvent en savoir plus sur notre GitLab ou Discord.",
"he_IL": "",
"it_IT": "Ryujinx è un emulatore della console Nintendo Switch™.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina GitHub.",
"it_IT": "Ryujinx è un emulatore della console Nintendo Switch™ 1.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina GitLab.",
"ja_JP": "",
"ko_KR": "Ryujinx는 Nintendo Switch™용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 GitHub 또는 Discord에서 자세한 내용을 확인할 수 있습니다.",
"no_NO": "Ryujinx er en emulator for Nintendo SwitchTM.\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på GitHub eller Discord.",
"ko_KR": "Ryujinx는 Nintendo Switch™ 1용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 GitLab 또는 Discord에서 자세한 내용을 확인할 수 있습니다.",
"no_NO": "Ryujinx er en emulator for Nintendo Switch™ 1\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på GitLab eller Discord.",
"pl_PL": "",
"pt_BR": "Ryujinx é um emulador de Nintendo Switch™.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitHub ou Discord.",
"ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitHub или Discord.",
"sv_SE": "Ryujinx är en emulator för Nintendo Switch™.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitHub eller Discord.",
"pt_BR": "Ryujinx é um emulador de Nintendo Switch™ 1.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitLab ou Discord.",
"ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™ 1.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitLab или Discord.",
"sv_SE": "Ryujinx är en emulator för Nintendo Switch™ 1.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitLab eller Discord.",
"th_TH": "",
"tr_TR": "",
"uk_UA": "Ryujinx — це емулятор для Nintendo Switch™.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitHub або в Discord.",
"zh_CN": "Ryujinx 是一个 Nintendo Switch™ 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitHub 或 Discord 上了解更多信息。\n",
"zh_TW": "Ryujinx 是一款 Nintendo Switch™ 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者可以在我們的 GitHub 或 Discord 上了解更多資訊。"
"uk_UA": "Ryujinx — це емулятор для Nintendo Switch™ 1.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitLab або в Discord.",
"zh_CN": "Ryujinx 是一个 Nintendo Switch™ 1 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitLab 或 Discord 上了解更多信息。\n",
"zh_TW": "Ryujinx 是一款 Nintendo Switch™ 1 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者可以在我們的 GitLab 或 Discord 上了解更多資訊。"
}
},
{
@@ -16943,7 +16968,7 @@
"th_TH": "ตัวเลือกนี้จะข้ามหน้าต่าง 'จัดการโปรไฟล์ผู้ใช้งาน' ระหว่างเล่นเกม โดยใช้โปรไฟล์ที่เลือกไว้ล่วงหน้า\n\nการสลับโปรไฟล์สามารถพบได้ใน 'ตั้งค่า' - 'จัดการโปรไฟล์ผู้ใช้งาน' เลือกโปรไฟล์ที่คุณต้องการก่อนโหลดเกม",
"tr_TR": "Bu seçenek, oyun sırasında 'Kullanıcı Profillerini Yönet' iletişim kutusunu atlar ve önceden seçilmiş bir profil kullanır.\n\nProfil değiştirme 'Seçenekler' - 'Kullanıcı Profillerini Yönet' bölümünde bulunur. Oyunu yüklemeden önce istediğiniz profili seçin.",
"uk_UA": "Ця опція пропускає діалогове вікно 'Керувати профілями користувачів' під час гри, використовуючи попередньо вибраний профіль.\n\nПеремикання профілів можна знайти в 'Налаштування' - 'Керувати профілями користувачів'. Виберіть потрібний профіль перед завантаженням гри.",
"zh_CN": "此选项跳过游戏过程中“管理用户账户”对话框使用预选的配置。\n\n可以在“设置” - “管理用户账户”中找到配置文件切换。 在加载游戏之前选择所需的配置文件。",
"zh_CN": "此选项跳过游戏过程中出现的 “管理用户账户” 对话框,使用预选的账户。\n\n可以在“设置” - “管理用户账户”中找到账户切换。 在加载游戏之前选择所需的账户。",
"zh_TW": "這個選項跳過遊戲過程中的「管理使用者設定檔」對話框,使用預先選取的設定。\n\n可以在「設定」-「管理使用者設定檔」中找到設定檔切換。 在載入遊戲前選擇您需要的設定檔。"
}
},
@@ -18368,7 +18393,7 @@
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_CN": "{0} FPS ({1}毫秒)",
"zh_TW": ""
}
},
@@ -23250,26 +23275,26 @@
{
"ID": "AboutChangelogButton",
"Translations": {
"ar_SA": "عرض سجل التغييرات على غيت هاب",
"de_DE": "Changelog in GitHub öffnen",
"el_GR": "Προβολή αρχείου αλλαγών στο GitHub",
"en_US": "View Changelog on GitHub",
"es_ES": "Ver registro de cambios en GitHub",
"fr_FR": "Voir le Changelog sur GitHub",
"he_IL": "צפה במידע אודות שינויים בגיטהב",
"it_IT": "Visualizza changelog su GitHub",
"ja_JP": "GitHub で更新履歴を表示",
"ko_KR": "GitHub에서 변경 내역 보기",
"no_NO": "Vis endringslogg på GitHub",
"pl_PL": "Zobacz listę zmian na GitHubie",
"pt_BR": "Ver Mudanças no GitHub",
"ru_RU": "Показать список изменений на GitHub",
"sv_SE": "Visa ändringslogg på GitHub",
"th_TH": "ดูประวัติการเปลี่ยนแปลงบน GitHub",
"tr_TR": "GitHub'da Değişiklikleri Görüntüle",
"uk_UA": "Переглянути журнал змін на GitHub",
"zh_CN": "在 Github 上查看更新日志",
"zh_TW": "在 GitHub 上檢視更新日誌"
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "View Changelog",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "ด",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
@@ -24484,7 +24509,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "불가",
"ko_KR": "불가",
"no_NO": "Ingenting",
"pl_PL": "",
"pt_BR": "Nada",
@@ -24748,4 +24773,4 @@
}
}
]
}
}

View File

@@ -601,6 +601,7 @@
010060200A4BE000,"Brawlout",ldn-untested;online,playable,2021-06-04 17:35:35
0100C1B00E1CA000,"Brawlout Demo",demo,playable,2021-02-13 22:46:53
010022C016DC8000,"Breakout: Recharged",slow,ingame,2022-11-06 15:32:57
010048A021C40000,"Breakout Beyond",,playable,2025-04-26 19:11:35
01000AA013A5E000,"Breathedge",UE4;nvdec,playable,2021-05-06 15:44:28
01003D50100F4000,"Breathing Fear",,playable,2020-07-14 15:12:29
010026800BB06000,"Brick Breaker",nvdec;online,playable,2020-12-15 18:26:23
@@ -2028,6 +2029,7 @@
0100628004BCE000,"Nights of Azure 2: Bride of the New Moon",crash;nvdec;regression,menus,2022-11-24 16:00:39
010042300C4F6000,"Nightshade百花百狼",nvdec,playable,2020-05-10 19:43:31
0100AA0008736000,"Nihilumbra",,playable,2020-05-10 16:00:12
01009FA01FF6C000,"Nikoderiko: The Magical World",gpu,ingame,2025-04-26 19:13:31
0100D03003F0E000,"Nine Parchments",ldn-untested,playable,2022-08-07 12:32:08
0100E2F014F46000,"NINJA GAIDEN Σ",nvdec,playable,2022-11-13 16:27:02
0100696014F4A000,"NINJA GAIDEN Σ2",nvdec,playable,2024-07-31 21:53:48
1 title_id game_name labels status last_updated
601 010060200A4BE000 Brawlout ldn-untested;online playable 2021-06-04 17:35:35
602 0100C1B00E1CA000 Brawlout Demo demo playable 2021-02-13 22:46:53
603 010022C016DC8000 Breakout: Recharged slow ingame 2022-11-06 15:32:57
604 010048A021C40000 Breakout Beyond playable 2025-04-26 19:11:35
605 01000AA013A5E000 Breathedge UE4;nvdec playable 2021-05-06 15:44:28
606 01003D50100F4000 Breathing Fear playable 2020-07-14 15:12:29
607 010026800BB06000 Brick Breaker nvdec;online playable 2020-12-15 18:26:23
2029 0100628004BCE000 Nights of Azure 2: Bride of the New Moon crash;nvdec;regression menus 2022-11-24 16:00:39
2030 010042300C4F6000 Nightshade/百花百狼 nvdec playable 2020-05-10 19:43:31
2031 0100AA0008736000 Nihilumbra playable 2020-05-10 16:00:12
2032 01009FA01FF6C000 Nikoderiko: The Magical World gpu ingame 2025-04-26 19:13:31
2033 0100D03003F0E000 Nine Parchments ldn-untested playable 2022-08-07 12:32:08
2034 0100E2F014F46000 NINJA GAIDEN Σ nvdec playable 2022-11-13 16:27:02
2035 0100696014F4A000 NINJA GAIDEN Σ2 nvdec playable 2024-07-31 21:53:48

View File

@@ -1,7 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />
<add key="RyubingPkgs" value="https://git.ryujinx.app/api/v4/projects/1/packages/nuget/index.json" />
</packageSources>
<!-- Define mappings by adding package patterns beneath the target source. -->
<!-- Ryujinx.LibHac packages will be restored from LibHacAlpha,
everything else from nuget.org. -->
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="LibHacAlpha">
<package pattern="Ryujinx.LibHac" />
</packageSource>
</packageSourceMapping>
</configuration>

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>

View File

@@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 7007; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@@ -566,9 +566,7 @@ namespace ARMeilleure.Translation.PTC
{
if (AreCarriersEmpty() || ContainsBlacklistedFunctions())
{
_infosStream.SetLength(0);
_relocsStream.SetLength(0);
_unwindInfosStream.SetLength(0);
ResetCarriersIfNeeded();
return;
}
@@ -875,7 +873,7 @@ namespace ARMeilleure.Translation.PTC
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
TranslatedFunction func = translator.Translate(address, executionMode, highCq);
TranslatedFunction func = translator.Translate(address, executionMode, highCq, pptcTranslation: true);
if (func == null)
{

View File

@@ -219,7 +219,7 @@ namespace ARMeilleure.Translation
}
}
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
{
ArmEmitterContext context = new(
Memory,
@@ -246,7 +246,7 @@ namespace ARMeilleure.Translation
context.Branch(context.GetLabel(address));
}
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter);
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter, pptcTranslation);
if (cfg == null)
{
@@ -326,7 +326,8 @@ namespace ARMeilleure.Translation
ArmEmitterContext context,
Block[] blocks,
out Range range,
out Counter<uint> counter)
out Counter<uint> counter,
bool pptcTranslation)
{
counter = null;
@@ -411,7 +412,10 @@ namespace ARMeilleure.Translation
if (opCode.Instruction.Emitter != null)
{
opCode.Instruction.Emitter(context);
if (opCode.Instruction.Name == InstName.Und && blkIndex == 0)
// if we're pre-compiling PPTC functions, and we hit an Undefined instruction as the first
// instruction in the block, mark the function as blacklisted
// this way, we don't pre-compile Exlaunch hooks, which allows ExeFS mods to run with PPTC
if (pptcTranslation && opCode.Instruction.Name == InstName.Und && blkIndex == 0)
{
range = new Range(rangeStart, rangeEnd);
return null;

View File

@@ -9,6 +9,7 @@ namespace Ryujinx.Common.Helper
public static readonly Regex Numeric = NumericRegex();
public static readonly Regex AmdGcn = AmdGcnRegex();
public static readonly Regex AmdRdna3 = AmdRdna3Regex();
public static readonly Regex NvidiaConsumerClass = NvidiaConsumerClassRegex();
public static readonly Regex DomainLp1Ns = DomainLp1NsRegex();
@@ -46,6 +47,9 @@ namespace Ryujinx.Common.Helper
"Radeon (((HD|R(5|7|9|X)) )?((M?[2-6]\\d{2}(\\D|$))|([7-8]\\d{3}(\\D|$))|Fury|Nano))|(Pro Duo)")]
internal static partial Regex AmdGcnRegex();
[GeneratedRegex("Radeon ([7-8](\\d{2}\\d?)[MS]|PRO [VW]7(\\d{2}\\d?)|RX 7\\d{3}([MS]?| XTX?| GRE)?)")]
public static partial Regex AmdRdna3Regex();
[GeneratedRegex("NVIDIA GeForce (R|G)?TX? (\\d{3}\\d?)M?")]
internal static partial Regex NvidiaConsumerClassRegex();

View File

@@ -4,6 +4,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>

View File

@@ -331,7 +331,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
context.GetOp<InstVotevtg>();
context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
// This instruction is proprietary and will not be implemented. Commenting it out to avoid false reports.
//context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
}
public static void Vset(EmitterContext context)

View File

@@ -1527,24 +1527,28 @@ namespace Ryujinx.Graphics.Vulkan
private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects)
{
if (_feedbackLoop != aspects)
// AMD RDNA 3 GPUs only
if (Gd.IsAmdRdna3)
{
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
if (_feedbackLoop != aspects)
{
DynamicState.SetFeedbackLoop(aspects);
}
else
{
_newState.FeedbackLoopAspects = aspects;
}
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
DynamicState.SetFeedbackLoop(aspects);
}
else
{
_newState.FeedbackLoopAspects = aspects;
}
_feedbackLoop = aspects;
_feedbackLoop = aspects;
return true;
return true;
}
}
return false;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool UpdateFeedbackLoop()

View File

@@ -1,6 +1,7 @@
using Ryujinx.Common.Memory;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.EXT;
using System;
namespace Ryujinx.Graphics.Vulkan
{
@@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
public uint ViewportsCount;
public Array16<Viewport> Viewports;
[Flags]
private enum DirtyFlags
{
None = 0,
@@ -190,14 +192,14 @@ namespace Ryujinx.Graphics.Vulkan
private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer)
{
ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0;
ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0;
if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0)
{
aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
}
if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0)
{
aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
}
api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects);
api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects);
}
}
}

View File

@@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Vulkan
internal bool IsAmdWindows { get; private set; }
internal bool IsIntelWindows { get; private set; }
internal bool IsAmdGcn { get; private set; }
internal bool IsAmdRdna3 { get; private set; }
internal bool IsNvidiaPreTuring { get; private set; }
internal bool IsIntelArc { get; private set; }
internal bool IsQualcommProprietary { get; private set; }
@@ -377,6 +378,10 @@ namespace Ryujinx.Graphics.Vulkan
GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}";
IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && Patterns.AmdGcn.IsMatch(GpuRenderer);
IsAmdRdna3 = Vendor == Vendor.Amd && (Patterns.AmdRdna3.IsMatch(GpuRenderer)
// ROG Ally (X) Device IDs
|| properties.DeviceID is 0x15BF or 0x15C8);
if (Vendor == Vendor.Nvidia)
{

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.HLE.FileSystem
public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator
{
public Result Create(ref SharedRef<IFileSystem> outEncryptedFileSystem,
ref SharedRef<IFileSystem> baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex,
ref readonly SharedRef<IFileSystem> baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex,
in EncryptionSeed encryptionSeed)
{
if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage)
@@ -18,7 +18,7 @@ namespace Ryujinx.HLE.FileSystem
}
// TODO: Reenable when AesXtsFileSystem is fixed.
outEncryptedFileSystem = SharedRef<IFileSystem>.CreateMove(ref baseFileSystem);
outEncryptedFileSystem = SharedRef<IFileSystem>.CreateMove(ref baseFileSystem.Ref);
return Result.Success;
}

View File

@@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS
{
string buildId = p switch
{
NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'),
NsoExecutable nso => Convert.ToHexString(nso.BuildId).TrimEnd('0'),
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'),
_ => string.Empty,
};

View File

@@ -753,17 +753,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs
public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context)
{
CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32();
using SharedRef<IFileSystem> fileSystem = new();
Result result = _baseFileSystemProxy.Get.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref, storageId);
if (result.IsFailure())
{
return (ResultCode)result.Value;
}
MakeObject(context, new FileSystemProxy.IFileSystem(ref fileSystem.Ref));
return ResultCode.Success;
Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId });
throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0
}
[CommandCmif(130)]
@@ -1028,7 +1020,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
{
ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context);
Result result = _baseFileSystemProxy.Get.GetRightsIdByPath(out RightsId rightsId, in path);
Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out _, in path, ContentAttributes.None);
if (result.IsFailure())
{
return (ResultCode)result.Value;
@@ -1044,7 +1036,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
{
ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context);
Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path);
Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path, ContentAttributes.None);
if (result.IsFailure())
{
return (ResultCode)result.Value;
@@ -1240,8 +1232,10 @@ namespace Ryujinx.HLE.HOS.Services.Fs
{
BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32();
ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context);
return (ResultCode)_baseFileSystemProxy.Get.SetBisRootForHost(partitionId, in path).Value;
Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path });
throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0
}
[CommandCmif(1001)]

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
NetworkError ConnectPrivate(ConnectPrivateRequest request);
ResultCode Reject(DisconnectReason disconnectReason, uint nodeId);
NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter);
void SetGameVersion(byte[] versionString);
void SetGameVersion(ReadOnlySpan<byte> versionString);
void SetStationAcceptPolicy(AcceptPolicy acceptPolicy);
void SetAdvertiseData(byte[] data);
bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData);

View File

@@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
// TODO: Call nn::arp::GetApplicationControlProperty here when implemented.
ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties;
foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId.ItemsRo)
foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId)
{
if (localCommunicationId == localCommunicationIdChecked)
{
@@ -1114,7 +1114,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
}
// TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented.
NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion.Items.ToArray());
NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion);
resultCode = ResultCode.Success;

View File

@@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
public void SetAdvertiseData(byte[] data) { }
public void SetGameVersion(byte[] versionString) { }
public void SetGameVersion(ReadOnlySpan<byte> versionString) { }
public void SetStationAcceptPolicy(AcceptPolicy acceptPolicy) { }

View File

@@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
_lanDiscovery.SetAdvertiseData(data);
}
public void SetGameVersion(byte[] versionString)
public void SetGameVersion(ReadOnlySpan<byte> versionString)
{
// NOTE: This method is not implemented in ldn_mitm
Logger.Stub?.PrintMsg(LogClass.ServiceLdn, "LdnMitmClient SetGameVersion");

View File

@@ -346,9 +346,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
}
}
public void SetGameVersion(byte[] versionString)
public void SetGameVersion(ReadOnlySpan<byte> versionString)
{
_gameVersion = versionString;
_gameVersion = versionString.ToArray();
if (_gameVersion.Length < 0x10)
{

View File

@@ -55,7 +55,13 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
_titleId = titleId;
// TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields.
_ratingAge = Array.ConvertAll(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.ItemsRo.ToArray(), Convert.ToInt32);
_ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length];
for (int i = 0; i < _ratingAge.Length; i++)
{
_ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]);
}
_parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag;
}
}

View File

@@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService
// Check if input title ids are in the whitelist.
foreach (ulong titleId in titleIds)
{
if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId))
if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.AsReadOnlySpan().Contains(titleId))
{
return (ResultCode)Am.ResultCode.ObjectInvalid;
}

View File

@@ -91,7 +91,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
if (string.IsNullOrWhiteSpace(programName))
{
programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString();
foreach (ApplicationControlProperty.ApplicationTitle appTitle in nacpData.Value.Title)
{
if (appTitle.Name[0] != 0)
continue;
programName = appTitle.NameString.ToString();
}
}
}

View File

@@ -9,6 +9,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Processes.Extensions;
using System;
@@ -158,7 +159,7 @@ namespace Ryujinx.HLE.Loaders.Processes
return false;
}
public bool LoadNxo(string path)
{
BlitStruct<ApplicationControlProperty> nacpData = new(1);
@@ -195,9 +196,19 @@ namespace Ryujinx.HLE.Loaders.Processes
programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString();
if ("Switch Verification" ==
nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString())
throw new InvalidOperationException();
if (string.IsNullOrWhiteSpace(programName))
{
programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString();
foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title)
{
if (nacpTitles.Name[0] != 0)
continue;
programName = nacpTitles.NameString.ToString();
}
}
if (nacpData.Value.PresenceGroupId != 0)

View File

@@ -258,7 +258,7 @@ namespace Ryujinx.HLE.Loaders.Processes
{
buildIds[i] = (executables[i] switch
{
NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()),
NsoExecutable nso => Convert.ToHexString(nso.BuildId),
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId),
_ => string.Empty
}).ToUpper();

View File

@@ -59,7 +59,13 @@ namespace Ryujinx.HLE.Loaders.Processes
if (string.IsNullOrWhiteSpace(Name))
{
Name = Array.Find(ApplicationControlProperties.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString();
foreach (ApplicationControlProperty.ApplicationTitle appTitle in ApplicationControlProperties.Title)
{
if (appTitle.Name[0] != 0)
continue;
Name = appTitle.NameString.ToString();
}
}
DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString();

View File

@@ -23,7 +23,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="LibHac" />
<PackageReference Include="Ryujinx.LibHac" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
<PackageReference Include="MsgPack.Cli" />
<PackageReference Include="SkiaSharp" />

View File

@@ -14,6 +14,6 @@
<ItemGroup>
<PackageReference Include="Concentus" />
<PackageReference Include="LibHac" />
<PackageReference Include="Ryujinx.LibHac" />
</ItemGroup>
</Project>

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -489,7 +489,7 @@ namespace Ryujinx.Headless
return false;
}
}
catch (ArgumentOutOfRangeException)
catch
{
Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");

View File

@@ -170,7 +170,8 @@
<EmbeddedResource Include="Assets\UIImages\Logo_Amiibo.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitLab.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitLab_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitLab_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
</ItemGroup>

View File

@@ -221,7 +221,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
NsoReader reader = new();
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
return Convert.ToHexString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", string.Empty).ToUpper()[..16];
return Convert.ToHexString(reader.Header.ModuleId).Replace("-", string.Empty).ToUpper()[..16];
}
}
}

View File

@@ -51,6 +51,26 @@ namespace Ryujinx.Ava.Systems.AppLibrary
public readonly IObservableCache<(TitleUpdateModel TitleUpdate, bool IsSelected), TitleUpdateModel> TitleUpdates;
public readonly IObservableCache<(DownloadableContentModel Dlc, bool IsEnabled), DownloadableContentModel> DownloadableContents;
private Gommon.Optional<TimeSpan> _totalTimePlayed;
public Gommon.Optional<TimeSpan> TotalTimePlayed
{
get => _totalTimePlayed;
private set
{
_totalTimePlayed = value;
_totalTimePlayedChanged.Call(value);
}
}
public event Action<Gommon.Optional<TimeSpan>> TotalTimePlayedRecalculated
{
add => _totalTimePlayedChanged.Add(value);
remove => _totalTimePlayedChanged.Remove(value);
}
private readonly Event<Gommon.Optional<TimeSpan>> _totalTimePlayedChanged = new();
private readonly byte[] _nspIcon;
private readonly byte[] _xciIcon;
private readonly byte[] _ncaIcon;
@@ -421,6 +441,10 @@ namespace Ryujinx.Ava.Systems.AppLibrary
Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);
GetApplicationInformation(ref controlHolder.Value, ref application);
if ("Switch Verification" == controlHolder.Value
.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString())
return false;
}
else
{
@@ -821,6 +845,22 @@ namespace Ryujinx.Ava.Systems.AppLibrary
}
}
public Task RefreshTotalTimePlayedAsync()
{
TotalTimePlayed = Gommon.Optional<TimeSpan>.None;
TimeSpan temporary = TimeSpan.Zero;
foreach (var installedApplication in Applications.Items)
{
temporary += LoadAndSaveMetaData(installedApplication.IdString).TimePlayed;
}
TotalTimePlayed = temporary;
return Task.CompletedTask;
}
public async Task RefreshLdn()
{
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
@@ -1363,7 +1403,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
{
_ = Enum.TryParse(DesiredLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
if (controlData.Title.Length > (int)desiredTitleLanguage)
{
data.Name = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
data.Developer = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
@@ -1376,7 +1416,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
if (string.IsNullOrWhiteSpace(data.Name))
{
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo)
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
{
if (!controlTitle.NameString.IsEmpty())
{
@@ -1389,7 +1429,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
if (string.IsNullOrWhiteSpace(data.Developer))
{
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo)
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
{
if (!controlTitle.PublisherString.IsEmpty())
{

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
return new Array(receivedData.Where(game =>
communicationId.Items.Contains(game.TitleId.ToULong())
communicationId.AsReadOnlySpan().Contains(game.TitleId.ToULong())
));
}

View File

@@ -157,8 +157,8 @@ namespace Ryujinx.Ava.Systems.Configuration
Multiplayer.LdnServer.Value = cff.LdnServer;
{
Hacks.ShowDirtyHacks.Value = cff.ShowDirtyHacks;
Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks: Hacks.ShowDirtyHacks.Value; // Get from global config only
DirtyHacks hacks = new (cff.DirtyHacks ?? []);
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix);

View File

@@ -24,8 +24,6 @@ namespace Ryujinx.Ava.UI.ViewModels
Version = RyujinxApp.FullAppName + "\n" + Program.Version;
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
GitLabLogo = LoadBitmap("resm:Ryujinx.Assets.UIImages.Logo_GitLab.png?assembly=Ryujinx");
RyujinxApp.ThemeChanged += Ryujinx_ThemeChanged;
}
@@ -43,6 +41,7 @@ namespace Ryujinx.Ava.UI.ViewModels
string themeName = isDarkTheme ? "Dark" : "Light";
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
GitLabLogo = LoadBitmap(LogoPathFormat.Format("GitLab", themeName));
}
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));

View File

@@ -25,6 +25,7 @@ using Ryujinx.Ava.UI.Renderer;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
@@ -112,6 +113,7 @@ namespace Ryujinx.Ava.UI.ViewModels
await Updater.BeginUpdateAsync(true);
});
private bool _showTotalTimePlayed;
private bool _showLoadProgress;
private bool _isGameRunning;
private bool _isAmiiboRequested;
@@ -197,6 +199,8 @@ namespace Ryujinx.Ava.UI.ViewModels
#if DEBUG
topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control));
#endif
Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated;
}
#region Properties
@@ -299,6 +303,24 @@ namespace Ryujinx.Ava.UI.ViewModels
OnPropertyChanged(nameof(ShowFirmwareStatus));
}
}
private void TotalTimePlayed_Recalculated(Optional<TimeSpan> ts)
{
ShowTotalTimePlayed = ts.HasValue;
if (ts.HasValue)
LocaleManager.Instance.SetDynamicValues(LocaleKeys.GameListLabelTotalTimePlayed, ValueFormatUtils.FormatTimeSpan(ts.Value));
}
public bool ShowTotalTimePlayed
{
get => _showTotalTimePlayed && EnableNonGameRunningControls;
set
{
_showTotalTimePlayed = value;
OnPropertyChanged();
}
}
public ApplicationData ListSelectedApplication
{

View File

@@ -113,6 +113,7 @@
Background="Transparent"
Click="Button_OnClick"
CornerRadius="15"
Tag="https://src.ryujinx.app"
ToolTip.Tip="{ext:Locale AboutGitLabUrlTooltipMessage}">
<Image Source="{Binding GitLabLogo}" />
</Button>

View File

@@ -6,7 +6,6 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using System.Threading.Tasks;
using Button = Avalonia.Controls.Button;
@@ -18,9 +17,6 @@ namespace Ryujinx.Ava.UI.Views.Dialog
public AboutView()
{
InitializeComponent();
GitRepoButton.Tag =
$"https://git.ryujinx.app/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}";
}
public static async Task Show()

View File

@@ -29,7 +29,7 @@
Margin="5"
VerticalAlignment="Center"
IsVisible="{Binding EnableNonGameRunningControls}">
<Grid Margin="0" ColumnDefinitions="Auto,Auto,Auto,*">
<Grid Margin="0" ColumnDefinitions="Auto,Auto,Auto,*,Auto,Auto,*">
<Button
Width="25"
Height="25"
@@ -68,6 +68,14 @@
IsVisible="{Binding StatusBarVisible}"
Maximum="{Binding StatusBarProgressMaximum}"
Value="{Binding StatusBarProgressValue}" />
<controls:MiniVerticalSeparator Grid.Column="4" IsVisible="{Binding ShowTotalTimePlayed}" />
<TextBlock
Grid.Column="5"
Margin="5,0,5,0"
VerticalAlignment="Center"
IsVisible="{Binding ShowTotalTimePlayed}"
Text="{ext:Locale GameListLabelTotalTimePlayed}">
</TextBlock>
</Grid>
</StackPanel>
<StackPanel

View File

@@ -717,6 +717,8 @@ namespace Ryujinx.Ava.UI.Windows
ShowNewContentAddedDialog(dlcLoaded, dlcRemoved, updatesLoaded, updatesRemoved);
}
Executor.ExecuteBackgroundAsync(ApplicationLibrary.RefreshTotalTimePlayedAsync);
_isLoading = false;
})