Compare commits

..

9 Commits

Author SHA1 Message Date
GreemDev
e9824c9053 Comment AppImage builds
It randomly started erroring in GitHub actions with exit code 8 but only sometimes, and I don't have the patience to debug it. I don't even use linux lol
2025-07-28 19:35:47 -05:00
LotP
d2037da65f Nullify Locales (ryubing/ryujinx!83)
See merge request ryubing/ryujinx!83
2025-07-28 19:35:47 -05:00
Rondo
8fe7d54f85 Changes to uk_UA (ryubing/ryujinx!84)
See merge request ryubing/ryujinx!84
2025-07-28 19:35:47 -05:00
Daenorth
b8f9f3e16a Edit TileIDs.cs (ryubing/ryujinx!81)
See merge request ryubing/ryujinx!81
2025-07-28 19:35:47 -05:00
Daenorth
7b1c8717ef Edit compatibility.csv (ryubing/ryujinx!80)
See merge request ryubing/ryujinx!80
2025-07-28 19:35:47 -05:00
GreemDev
6122fa204f simplify completion callback 2025-07-28 17:58:54 -05:00
GreemDev
217fd90568 Use a single parser execution per text box update
Before it would: parse, compile, then execute for getting the formatted result, then run the suggestions function which did parsing on its own. It has now been moved to the new ParseAndGetCompletions function which returns the used ParserResult, saving some work.
2025-07-27 17:35:06 -05:00
GreemDev
95157c0cfd make ApplicationLibrary implement IStarscriptObject 2025-07-27 17:32:39 -05:00
GreemDev
8a3ccaafe3 basic starscript support + a textbox that provides the starscript executed result & compiled script as well as suggestions 2025-07-27 01:09:59 -05:00
18 changed files with 1194 additions and 146 deletions

View File

@@ -55,6 +55,7 @@
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="Starscript.Net" Version="1.0.36" />
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
<PackageVersion Include="System.Management" Version="9.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />

File diff suppressed because it is too large Load Diff

View File

@@ -188,8 +188,6 @@
01003DD00BFEE000,"Airheart - Tales of broken Wings",,playable,2021-02-26 15:20:27
01007F100DE52000,"Akane",nvdec,playable,2022-07-21 00:12:18
01009A800F0C8000,"Akash: Path of the Five",gpu;nvdec,ingame,2020-12-14 22:33:12
01009E8012976000,"AKIBA'S TRIP: Hellbound & Debriefed",,playable,2025-07-30 23:22:47
0100D74019A0E000,"AKIBA'S TRIP: Undead & Undressed Director's Cut",,playable,2025-07-31 13:58:42
010053100B0EA000,"Akihabara - Feel the Rhythm Remixed",,playable,2021-02-22 14:39:35
0100D4C00EE0C000,"Akuarium",slow,playable,2020-12-12 23:43:36
010026E00FEBE000,"Akuto: Showdown",,playable,2020-08-04 19:43:27
@@ -1097,7 +1095,6 @@
0100F9600E746000,"ESP Ra.De. Psi",audio;slow,ingame,2024-03-07 15:05:08
010073000FE18000,"Esports powerful pro yakyuu 2020",gpu;crash;Needs More Attention,ingame,2024-04-29 05:34:14
01004F9012FD8000,"Estranged: The Departure",nvdec;UE4,playable,2022-10-24 10:37:58
010018f01e0a0000,"Eternights",,playable,2025-07-30 12:10:24
0100CB900B498000,"Eternum Ex",,playable,2021-01-13 20:28:32
010092501EB2C000,"Europa (Demo)",gpu;crash;UE4,ingame,2024-04-23 10:47:12
01007BE0160D6000,"EVE ghost enemies",gpu,ingame,2023-01-14 03:13:30
@@ -1243,8 +1240,6 @@
010003F00BD48000,"Friday the 13th: Killer Puzzle",,playable,2021-01-28 01:33:38
010092A00C4B6000,"Friday the 13th: The Game Ultimate Slasher Edition",nvdec;online-broken;UE4,playable,2022-09-06 17:33:27
0100F200178F4000,"FRONT MISSION 1st: Remake",,playable,2023-06-09 07:44:24
0100c4e018a24000,"FRONT MISSION 2: Remake",,playable,2025-07-30 12:11:23
01007E6019872000,"FRONT MISSION 3: Remake",,playable,2025-07-30 12:12:02
0100861012474000,"Frontline Zed",,playable,2020-10-03 12:55:59
0100B5300B49A000,"Frost",,playable,2022-07-27 12:00:36
010038A007AA4000,"FruitFall Crush",,playable,2020-10-20 11:33:33
@@ -1523,7 +1518,6 @@
010095C016C14000,"Iridium",,playable,2022-08-05 23:19:53
0100AD300B786000,"Iris School of Wizardry -Vinculum Hearts-",,playable,2022-12-05 13:11:15
0100945012168000,"Iris.Fall",nvdec,playable,2022-10-18 13:40:22
010059801B736000,"IronFall: Invasion",,playable,2025-07-30 11:42:30
01005270118D6000,"Iron Wings",slow,ingame,2022-08-07 08:32:57
01004DB003E6A000,"IRONCAST",,playable,2021-01-13 13:54:29
0100E5700CD56000,"Irony Curtain: From Matryoshka with Love",,playable,2021-06-04 20:12:37
@@ -2312,7 +2306,6 @@
010077B00BDD8000,"Professional Farmer: Nintendo Switch™ Edition",slow,playable,2020-12-16 13:38:19
010018300C83A000,"Professor Lupo and his Horrible Pets",,playable,2020-06-12 00:08:45
0100D1F0132F6000,"Professor Lupo: Ocean",,playable,2021-04-14 16:33:33
0100c3a017834000,"Prodeus",,playable,2025-07-30 12:07:52
0100BBD00976C000,"Project Highrise: Architect's Edition",,playable,2022-08-10 17:19:12
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
@@ -2775,7 +2768,7 @@
0100E6B0115FC000,"Star99",online,menus,2021-11-26 14:18:51
01002100137BA000,"Stardash",,playable,2021-01-21 16:31:19
0100E65002BB8000,"Stardew Valley",online-broken;ldn-untested,playable,2024-02-14 03:11:19
01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",,playable,2025-07-30 12:09:37
01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",services-horizon;crash;Needs Update,nothing,2024-05-05 17:25:11
010098E010FDA000,"Starlit Adventures Golden Stars",,playable,2020-11-21 12:14:43
01001BB00AC26000,"STARSHIP AVENGER Operation: Take Back Earth",,playable,2021-01-12 15:52:55
010000700A572000,"State of Anarchy: Master of Mayhem",nvdec,playable,2021-01-12 19:00:05
@@ -2983,7 +2976,6 @@
0100C2E0129A6000,"The Executioner",nvdec,playable,2021-01-23 00:31:28
01006050114D4000,"The Experiment: Escape Room",gpu,ingame,2022-09-30 13:20:35
0100B5900DFB2000,"The Eyes of Ara",,playable,2022-09-16 14:44:06
0100BA5013E52000,"The Falconeer: Warrior Edition",,playable,2025-07-30 12:04:50
01002DD00AF9E000,"The Fall",gpu,ingame,2020-05-31 23:31:16
01003E5002320000,"The Fall Part 2: Unbound",,playable,2021-11-06 02:18:08
0100CDC00789E000,"The Final Station",nvdec,playable,2022-08-22 15:54:39
@@ -3206,7 +3198,6 @@
010000400F582000,"TT Isle of Man Ride on the Edge 2",gpu;nvdec;online-broken,ingame,2022-09-30 22:13:05
0100752011628000,"TTV2",,playable,2020-11-27 13:21:36
0100AFE00452E000,"Tumblestone",,playable,2021-01-07 17:49:20
0100D1A01D7BA000,"Turbo Overkill",,playable,2025-07-30 12:08:57
010085500D5F6000,"Turok",gpu,ingame,2021-06-04 13:16:24
0100CDC00D8D6000,"Turok 2: Seeds of Evil",gpu;vulkan,ingame,2022-09-12 17:50:05
010004B0130C8000,"Turrican Flashback",audout,playable,2021-08-30 10:07:56
@@ -3230,8 +3221,6 @@
0100592005164000,"UNBOX: Newbie's Adventure",UE4,playable,2022-08-29 13:12:56
01002D900C5E4000,"Uncanny Valley",nvdec,playable,2021-06-04 13:28:45
010076F011F54000,"Undead & Beyond",nvdec,playable,2022-10-04 09:11:18
01009B700D0B8000,"Undead Horde",,playable,2025-07-30 12:05:05
0100FC301A878000,"Undead Horde 2: Necropolis",,playable,2025-07-30 12:06:07
01008F3013E4E000,"Under Leaves",,playable,2021-05-22 18:13:58
010080B00AD66000,"Undertale",,playable,2022-08-31 17:31:46
01008F80049C6000,"Unepic",,playable,2024-01-15 17:03:00
1 title_id game_name labels status last_updated
188 01003DD00BFEE000 Airheart - Tales of broken Wings playable 2021-02-26 15:20:27
189 01007F100DE52000 Akane nvdec playable 2022-07-21 00:12:18
190 01009A800F0C8000 Akash: Path of the Five gpu;nvdec ingame 2020-12-14 22:33:12
01009E8012976000 AKIBA'S TRIP: Hellbound & Debriefed playable 2025-07-30 23:22:47
0100D74019A0E000 AKIBA'S TRIP: Undead & Undressed Director's Cut playable 2025-07-31 13:58:42
191 010053100B0EA000 Akihabara - Feel the Rhythm Remixed playable 2021-02-22 14:39:35
192 0100D4C00EE0C000 Akuarium slow playable 2020-12-12 23:43:36
193 010026E00FEBE000 Akuto: Showdown playable 2020-08-04 19:43:27
1095 0100F9600E746000 ESP Ra.De. Psi audio;slow ingame 2024-03-07 15:05:08
1096 010073000FE18000 Esports powerful pro yakyuu 2020 gpu;crash;Needs More Attention ingame 2024-04-29 05:34:14
1097 01004F9012FD8000 Estranged: The Departure nvdec;UE4 playable 2022-10-24 10:37:58
010018f01e0a0000 Eternights playable 2025-07-30 12:10:24
1098 0100CB900B498000 Eternum Ex playable 2021-01-13 20:28:32
1099 010092501EB2C000 Europa (Demo) gpu;crash;UE4 ingame 2024-04-23 10:47:12
1100 01007BE0160D6000 EVE ghost enemies gpu ingame 2023-01-14 03:13:30
1240 010003F00BD48000 Friday the 13th: Killer Puzzle playable 2021-01-28 01:33:38
1241 010092A00C4B6000 Friday the 13th: The Game Ultimate Slasher Edition nvdec;online-broken;UE4 playable 2022-09-06 17:33:27
1242 0100F200178F4000 FRONT MISSION 1st: Remake playable 2023-06-09 07:44:24
0100c4e018a24000 FRONT MISSION 2: Remake playable 2025-07-30 12:11:23
01007E6019872000 FRONT MISSION 3: Remake playable 2025-07-30 12:12:02
1243 0100861012474000 Frontline Zed playable 2020-10-03 12:55:59
1244 0100B5300B49A000 Frost playable 2022-07-27 12:00:36
1245 010038A007AA4000 FruitFall Crush playable 2020-10-20 11:33:33
1518 010095C016C14000 Iridium playable 2022-08-05 23:19:53
1519 0100AD300B786000 Iris School of Wizardry -Vinculum Hearts- playable 2022-12-05 13:11:15
1520 0100945012168000 Iris.Fall nvdec playable 2022-10-18 13:40:22
010059801B736000 IronFall: Invasion playable 2025-07-30 11:42:30
1521 01005270118D6000 Iron Wings slow ingame 2022-08-07 08:32:57
1522 01004DB003E6A000 IRONCAST playable 2021-01-13 13:54:29
1523 0100E5700CD56000 Irony Curtain: From Matryoshka with Love playable 2021-06-04 20:12:37
2306 010077B00BDD8000 Professional Farmer: Nintendo Switch™ Edition slow playable 2020-12-16 13:38:19
2307 010018300C83A000 Professor Lupo and his Horrible Pets playable 2020-06-12 00:08:45
2308 0100D1F0132F6000 Professor Lupo: Ocean playable 2021-04-14 16:33:33
0100c3a017834000 Prodeus playable 2025-07-30 12:07:52
2309 0100BBD00976C000 Project Highrise: Architect's Edition playable 2022-08-10 17:19:12
2310 0100ACE00DAB6000 Project Nimbus: Complete Edition nvdec;UE4;vulkan-backend-bug playable 2022-08-10 17:35:43
2311 01002980140F6000 Project TRIANGLE STRATEGY™ Debut Demo UE4;demo playable 2022-10-24 21:40:27
2768 0100E6B0115FC000 Star99 online menus 2021-11-26 14:18:51
2769 01002100137BA000 Stardash playable 2021-01-21 16:31:19
2770 0100E65002BB8000 Stardew Valley online-broken;ldn-untested playable 2024-02-14 03:11:19
2771 01002CC003FE6000 Starlink: Battle for Atlas™ Digital Edition services-horizon;crash;Needs Update playable nothing 2025-07-30 12:09:37 2024-05-05 17:25:11
2772 010098E010FDA000 Starlit Adventures Golden Stars playable 2020-11-21 12:14:43
2773 01001BB00AC26000 STARSHIP AVENGER Operation: Take Back Earth playable 2021-01-12 15:52:55
2774 010000700A572000 State of Anarchy: Master of Mayhem nvdec playable 2021-01-12 19:00:05
2976 0100C2E0129A6000 The Executioner nvdec playable 2021-01-23 00:31:28
2977 01006050114D4000 The Experiment: Escape Room gpu ingame 2022-09-30 13:20:35
2978 0100B5900DFB2000 The Eyes of Ara playable 2022-09-16 14:44:06
0100BA5013E52000 The Falconeer: Warrior Edition playable 2025-07-30 12:04:50
2979 01002DD00AF9E000 The Fall gpu ingame 2020-05-31 23:31:16
2980 01003E5002320000 The Fall Part 2: Unbound playable 2021-11-06 02:18:08
2981 0100CDC00789E000 The Final Station nvdec playable 2022-08-22 15:54:39
3198 010000400F582000 TT Isle of Man Ride on the Edge 2 gpu;nvdec;online-broken ingame 2022-09-30 22:13:05
3199 0100752011628000 TTV2 playable 2020-11-27 13:21:36
3200 0100AFE00452E000 Tumblestone playable 2021-01-07 17:49:20
0100D1A01D7BA000 Turbo Overkill playable 2025-07-30 12:08:57
3201 010085500D5F6000 Turok gpu ingame 2021-06-04 13:16:24
3202 0100CDC00D8D6000 Turok 2: Seeds of Evil gpu;vulkan ingame 2022-09-12 17:50:05
3203 010004B0130C8000 Turrican Flashback audout playable 2021-08-30 10:07:56
3221 0100592005164000 UNBOX: Newbie's Adventure UE4 playable 2022-08-29 13:12:56
3222 01002D900C5E4000 Uncanny Valley nvdec playable 2021-06-04 13:28:45
3223 010076F011F54000 Undead & Beyond nvdec playable 2022-10-04 09:11:18
01009B700D0B8000 Undead Horde playable 2025-07-30 12:05:05
0100FC301A878000 Undead Horde 2: Necropolis playable 2025-07-30 12:06:07
3224 01008F3013E4E000 Under Leaves playable 2021-05-22 18:13:58
3225 010080B00AD66000 Undertale playable 2022-08-31 17:31:46
3226 01008F80049C6000 Unepic playable 2024-01-15 17:03:00

View File

@@ -73,6 +73,7 @@
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
<PackageReference Include="SPB" />
<PackageReference Include="Starscript.Net"/>
<PackageReference Include="SharpZipLib" />
</ItemGroup>

View File

@@ -14,6 +14,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Systems.Configuration.System;
using Ryujinx.Ava.Systems.Starscript;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
@@ -25,6 +26,7 @@ using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Loaders.Npdm;
using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.HLE.Utilities;
using Starscript;
using System;
using System.Collections.Generic;
using System.IO;
@@ -41,7 +43,7 @@ using TimeSpan = System.TimeSpan;
namespace Ryujinx.Ava.Systems.AppLibrary
{
public class ApplicationLibrary
public class ApplicationLibrary : IStarscriptObject
{
public Language DesiredLanguage { get; set; }
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
@@ -1611,5 +1613,14 @@ namespace Ryujinx.Ava.Systems.AppLibrary
ApplicationData newApplication = newApplications.First(it => it.IdBase == appIdBase);
_applications.AddOrUpdate(newApplication);
}
private ValueMap _starscriptMap;
public ValueMap ToStarscript()
{
_starscriptMap ??= StarscriptHelper.Wrap(this);
return _starscriptMap;
}
}
}

View File

@@ -0,0 +1,29 @@
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Common;
using Starscript;
namespace Ryujinx.Ava.Systems.Starscript
{
public static class RyujinxStarscript
{
public static readonly StarscriptHypervisor Hypervisor = StarscriptHypervisor.Create().WithStandardLibrary(true);
static RyujinxStarscript()
{
Hypervisor.Set("ryujinx.releaseChannel",
ReleaseInformation.IsCanaryBuild
? "Canary"
: ReleaseInformation.IsReleaseBuild
? "Stable"
: "Custom");
Hypervisor.Set("ryujinx.version", Program.Version);
Hypervisor.Set("appLibrary", RyujinxApp.MainWindow.ApplicationLibrary);
Hypervisor.Set("currentApplication", () =>
RyujinxApp.MainWindow.ApplicationLibrary.FindApplication(
RyujinxApp.MainWindow.ViewModel.AppHost?.ApplicationId ?? 0,
out ApplicationData appData)
? StarscriptHelper.Wrap(appData)
: Value.Null);
}
}
}

View File

@@ -0,0 +1,68 @@
using Gommon;
using Ryujinx.Ava.Systems.AppLibrary;
using Starscript;
using System;
namespace Ryujinx.Ava.Systems.Starscript
{
public static class StarscriptHelper
{
public static ValueMap Wrap(ApplicationLibrary appLib)
{
ValueMap lMap = new();
lMap.Set("appCount", () => appLib.Applications.Count);
lMap.Set("dlcCount", () => appLib.DownloadableContents.Count);
lMap.Set("updateCount", () => appLib.TitleUpdates.Count);
lMap.Set("has", ctx =>
{
ulong titleId;
try
{
titleId = ctx.Constrain(Constraint.ExactlyOneArgument).NextString(1).ToULong();
}
catch (FormatException)
{
throw ctx.Error(
$"Invalid input to {ctx.FormattedName}; input must be a hexadecimal number in a string.");
}
return appLib.FindApplication(titleId, out _);
});
lMap.Set("get", ctx =>
{
ulong titleId;
try
{
titleId = ctx.Constrain(Constraint.ExactlyOneArgument).NextString(1).ToULong();
}
catch (FormatException)
{
throw ctx.Error(
$"Invalid input to {ctx.FormattedName}; input must be a hexadecimal number in a string.");
}
return appLib.FindApplication(titleId,
out ApplicationData applicationData)
? Wrap(applicationData)
: null;
});
return lMap;
}
public static ValueMap Wrap(ApplicationData appData)
{
ValueMap aMap = new();
aMap.Set("name", appData.Name);
aMap.Set("version", appData.Version);
aMap.Set("developer", appData.Developer);
aMap.Set("fileExtension", appData.FileExtension);
aMap.Set("fileSize", appData.FileSizeString);
aMap.Set("hasLdnGames", appData.HasLdnGames);
aMap.Set("timePlayed", appData.TimePlayedString);
aMap.Set("isFavorite", appData.Favorite);
return aMap;
}
}
}

View File

@@ -0,0 +1,21 @@
<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:local="using:Ryujinx.Ava.Systems.Starscript"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ryujinx.Ava.Systems.Starscript.StarscriptTextBox"
x:DataType="local:StarscriptTextBoxViewModel">
<StackPanel Spacing="10">
<TextBlock Text="{Binding ErrorMessage}" IsVisible="{Binding HasError}"/>
<TextBlock Text="{Binding CurrentScriptResult}" IsVisible="{Binding !HasError}"/>
<AutoCompleteBox Name="InputBox"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
FilterMode="Custom"
MinimumPrefixLength="0"
MaxDropDownHeight="400">
</AutoCompleteBox>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,87 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Humanizer;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Starscript;
using Starscript.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Systems.Starscript
{
public partial class StarscriptTextBox : RyujinxControl<StarscriptTextBoxViewModel>
{
public IReadOnlyList<string> CurrentSuggestions => ViewModel.CurrentSuggestions;
public ParserResult CurrentScriptSource => ViewModel.CurrentScriptSource;
public Exception Exception => ViewModel.Exception;
public Script CurrentScript => ViewModel.CurrentScript;
public StringSegment CurrentScriptResult => ViewModel.CurrentScriptResult;
public StarscriptTextBox()
{
InitializeComponent();
InputBox.AsyncPopulator = GetSuggestionsAsync;
InputBox.MinimumPopulateDelay = 0.Seconds();
InputBox.TextFilter = (_, _) => true;
InputBox.TextSelector = (text, suggestion) =>
{
if (text is not null && suggestion is null)
return text;
if (text is null && suggestion is not null)
return suggestion;
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (text is null && suggestion is null)
return string.Empty;
var sb = new StringBuilder(text.Length + suggestion.Length + 1);
sb.Append(text);
for (int i = 0; i < suggestion.Length - 1; i++)
{
if (text.EndsWith(suggestion[..(suggestion.Length - i - 1)]))
{
suggestion = suggestion[(suggestion.Length - i - 1)..];
break;
}
}
sb.Append(suggestion);
return sb.ToString();
};
Style textStyle = new(x => x.OfType<AutoCompleteBox>().Descendant().OfType<TextBlock>());
textStyle.Setters.Add(new Setter(MarginProperty, new Thickness(0, 0)));
Styles.Add(textStyle);
}
private Task<IEnumerable<object>> GetSuggestionsAsync(string input, CancellationToken token)
=> Task.FromResult(ViewModel.GetSuggestions(input, token));
public static StarscriptTextBox Create(StarscriptHypervisor hv)
=> new() { ViewModel = new StarscriptTextBoxViewModel(hv) };
public static async Task Show()
{
ContentDialog contentDialog = new()
{
PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty,
CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
Content = new StarscriptTextBox { ViewModel = new() }
};
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles());
}
}
}

View File

@@ -0,0 +1,126 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels;
using Starscript;
using Starscript.Internal;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
namespace Ryujinx.Ava.Systems.Starscript
{
public partial class StarscriptTextBoxViewModel : BaseModel
{
private readonly StarscriptHypervisor _hv;
public StarscriptTextBoxViewModel(StarscriptHypervisor hv = null)
{
_hv = hv ?? RyujinxStarscript.Hypervisor;
}
public ObservableCollection<string> CurrentSuggestions { get; } = [];
[ObservableProperty] private bool _hasError;
[ObservableProperty] private StringSegment _currentScriptResult;
[ObservableProperty] private string _errorMessage;
private Exception _exception;
private ParserResult _currentScriptSource;
private Script _currentScript;
public Exception Exception
{
get => _exception;
set
{
ErrorMessage = (_exception = value) switch
{
ParseException pe => pe.Error.ToString(),
StarscriptException se => se.Message,
_ => string.Empty
};
HasError = value is not null;
OnPropertyChanged();
}
}
public ParserResult CurrentScriptSource
{
get => _currentScriptSource;
set
{
_currentScriptSource = value;
if (value is null)
{
CurrentScript = null;
CurrentScriptResult = null;
Exception = null;
return;
}
CurrentScript = Compiler.SingleCompile(value);
Exception = null;
OnPropertyChanged();
}
}
public Script CurrentScript
{
get => _currentScript;
private set
{
try
{
CurrentScriptResult = value?.Execute(_hv)!;
_currentScript = value;
Exception = null;
}
catch (StarscriptException se)
{
_currentScript = null;
CurrentScriptResult = null;
Exception = se;
}
OnPropertyChanged();
}
}
public void ReExecuteScript()
{
if (_currentScript is null) return;
try
{
CurrentScriptResult = _currentScript.Execute(_hv)!;
}
catch (StarscriptException se)
{
CurrentScriptResult = null;
Exception = se;
}
}
public IEnumerable<object> GetSuggestions(string input, CancellationToken token)
{
CurrentSuggestions.Clear();
CurrentScriptSource = _hv.ParseAndGetCompletions(input, input.Length, CompletionCallback, token);
if (CurrentScriptSource.HasErrors)
{
Exception = new ParseException(CurrentScriptSource.Errors.First());
}
OnPropertyChanged(nameof(CurrentSuggestions));
return CurrentSuggestions;
}
private void CompletionCallback(string result, bool isFunction) => CurrentSuggestions.Add(isFunction ? $"{result}(" : result);
}
}

View File

@@ -14,7 +14,8 @@
Command="{Binding ToggleFavorite}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuToggleFavorite}"
Icon="{ext:Icon fa-solid fa-star}" />
Icon="{ext:Icon fa-solid fa-star}"
ToolTip.Tip="{ext:Locale GameListContextMenuToggleFavoriteToolTip}" />
<MenuItem
Command="{Binding CreateApplicationShortcut}"
CommandParameter="{Binding}"
@@ -46,53 +47,62 @@
Command="{Binding OpenApplicationData}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuShowGameData}"
Icon="{ext:Icon fa-solid fa-chart-line}" />
Icon="{ext:Icon fa-solid fa-chart-line}"
ToolTip.Tip="{ext:Locale GameListContextMenuShowGameDataToolTip}"/>
<Separator />
<MenuItem
Command="{Binding OpenUserSaveDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenUserSaveDirectory}"
Icon="{ext:Icon fa-solid fa-sd-card}"
IsEnabled="{Binding OpenUserSaveDirectoryEnabled}" />
IsEnabled="{Binding OpenUserSaveDirectoryEnabled}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenUserSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenDeviceSaveDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenDeviceSaveDirectory}"
Icon="{ext:Icon fa-solid fa-hard-drive}"
IsEnabled="{Binding OpenDeviceSaveDirectoryEnabled}" />
IsEnabled="{Binding OpenDeviceSaveDirectoryEnabled}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenDeviceSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenBcatSaveDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenBcatSaveDirectory}"
Icon="{ext:Icon fa-solid fa-box-archive}"
IsEnabled="{Binding OpenBcatSaveDirectoryEnabled}" />
IsEnabled="{Binding OpenBcatSaveDirectoryEnabled}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenBcatSaveDirectoryToolTip}" />
<Separator />
<MenuItem
Command="{Binding OpenTitleUpdateManager}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageTitleUpdates}"
Icon="{ext:Icon fa-solid fa-code-compare}" />
Icon="{ext:Icon fa-solid fa-code-compare}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageTitleUpdatesToolTip}" />
<MenuItem
Command="{Binding OpenDownloadableContentManager}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageDlc}"
Icon="{ext:Icon fa-solid fa-download}" />
Icon="{ext:Icon fa-solid fa-download}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageDlcToolTip}" />
<MenuItem
Command="{Binding OpenCheatManager}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageCheat}"
Icon="{ext:Icon fa-solid fa-code}" />
Icon="{ext:Icon fa-solid fa-code}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageCheatToolTip}" />
<MenuItem
Command="{Binding OpenModManager}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageMod}"
Icon="{ext:Icon fa-solid fa-sliders}" />
Icon="{ext:Icon fa-solid fa-sliders}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageModToolTip}" />
<Separator />
<MenuItem
Command="{Binding OpenModsDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenModsDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" />
Icon="{ext:Icon fa-solid fa-folder}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenModsDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenSdModsDirectory}"
CommandParameter="{Binding}"
@@ -130,12 +140,14 @@
Command="{Binding OpenPtcDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" />
Icon="{ext:Icon fa-solid fa-folder}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenShaderCacheDirectory}"
CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" />
Icon="{ext:Icon fa-solid fa-folder}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip}" />
</MenuItem>
<MenuItem Header="{ext:Locale GameListContextMenuExtractData}" Icon="{ext:Icon fa-solid fa-file-export}">
<MenuItem

View File

@@ -63,15 +63,18 @@
<MenuItem
Command="{Binding OpenRyujinxFolder}"
Header="{ext:Locale MenuBarFileOpenEmuFolder}"
Icon="{ext:Icon fa-solid fa-folder-closed}" />
Icon="{ext:Icon fa-solid fa-folder-closed}"
ToolTip.Tip="{ext:Locale OpenRyujinxFolderTooltip}" />
<MenuItem
Command="{Binding OpenScreenshotsFolder}"
Header="{ext:Locale MenuBarFileOpenScreenshotsFolder}"
Icon="{ext:Icon fa-solid fa-desktop}" />
Icon="{ext:Icon fa-solid fa-desktop}"
ToolTip.Tip="{ext:Locale OpenScreenshotFolderTooltip}"/>
<MenuItem
Command="{Binding OpenLogsFolder}"
Header="{ext:Locale MenuBarFileOpenLogsFolder}"
Icon="{ext:Icon fa-solid fa-file-lines}" />
Icon="{ext:Icon fa-solid fa-file-lines}"
ToolTip.Tip="{ext:Locale OpenRyujinxLogsTooltip}" />
<Separator />
<MenuItem
Name="CloseRyujinxMenuItem"
@@ -146,6 +149,7 @@
Padding="0"
Header="{ext:Locale MenuBarOptionsSettings}"
Icon="{ext:Icon fa-solid fa-gear}"
ToolTip.Tip="{ext:Locale OpenSettingsTooltip}"
Classes="withCheckbox">
</MenuItem>
<MenuItem
@@ -154,6 +158,7 @@
Header="{ext:Locale MenuBarOptionsManageUserProfiles}"
Icon="{ext:Icon fa-solid fa-user}"
IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale OpenProfileManagerTooltip}"
Classes="withCheckbox">
</MenuItem>
</MenuItem>
@@ -246,12 +251,18 @@
<MenuItem
Name="AboutWindowMenuItem"
Header="{ext:Locale MenuBarHelpAbout}"
Icon="{ext:Icon fa-solid fa-circle-info}" />
Icon="{ext:Icon fa-solid fa-circle-info}"
ToolTip.Tip="{ext:Locale OpenAboutTooltip}" />
<MenuItem
Name="StarscriptDebugMenuItem"
Header="Debug Starscript"
Icon="{ext:Icon fa-solid fa-star}" />
<MenuItem
Name="UpdateMenuItem"
IsEnabled="{Binding CanUpdate}"
Header="{ext:Locale MenuBarHelpCheckForUpdates}"
Icon="{ext:Icon fa-solid fa-rotate}" />
Icon="{ext:Icon fa-solid fa-rotate}"
ToolTip.Tip="{ext:Locale CheckUpdatesTooltip}" />
<MenuItem
Name="CompatibilityListMenuItem"
Header="{ext:Locale CompatibilityListOpen}"

View File

@@ -8,6 +8,7 @@ using LibHac.Ns;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Systems.Starscript;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
@@ -51,6 +52,8 @@ namespace Ryujinx.Ava.UI.Views.Main
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show());
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
StarscriptDebugMenuItem.Command = Commands.Create(StarscriptTextBox.Show);
FaqMenuItem.Command =
SetupGuideMenuItem.Command =

View File

@@ -236,6 +236,7 @@
Minimum="0"
SmallChange="0.01"
TickFrequency="0.05"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Value="{Binding Volume}" />
</Grid>
</Flyout>

View File

@@ -49,7 +49,8 @@
<TextBlock
Margin="10,0"
VerticalAlignment="Center"
Text="{ext:Locale IconSize}" />
Text="{ext:Locale IconSize}"
ToolTip.Tip="{ext:Locale IconSizeTooltip}" />
<controls:SliderScroll
Width="150"
Height="35"
@@ -60,6 +61,7 @@
Maximum="4"
Minimum="1"
TickFrequency="1"
ToolTip.Tip="{ext:Locale IconSizeTooltip}"
Value="{Binding GridSizeScale}" />
<CheckBox
Margin="0"

View File

@@ -33,7 +33,6 @@
Width="250" />
<ComboBox SelectedIndex="{Binding AudioBackend}"
Width="350"
ToolTip.Tip="{ext:Locale AudioBackendTooltip}"
HorizontalContentAlignment="Left">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemAudioBackendDummy}" />
@@ -52,8 +51,10 @@
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemAudioVolume}"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Width="250" />
<ui:NumberBox Value="{Binding Volume}"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Width="350"
SmallChange="1"
LargeChange="10"
@@ -65,6 +66,7 @@
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<controls:SliderScroll Value="{Binding Volume}"
Margin="250,0,0,0"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Minimum="0"
Maximum="100"
SmallChange="1"

View File

@@ -285,10 +285,12 @@
Spacing="10">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale ShaderDumpPathTooltip}"
Text="{ext:Locale SettingsTabGraphicsShaderDumpPath}"
Width="250" />
<TextBox Text="{Binding ShaderDumpPath}"
Width="350" />
Width="350"
ToolTip.Tip="{ext:Locale ShaderDumpPathTooltip}" />
</StackPanel>
</StackPanel>
</StackPanel>

View File

@@ -40,6 +40,7 @@
Width="250" />
<ComboBox
SelectedIndex="{Binding Region}"
ToolTip.Tip="{ext:Locale RegionTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
@@ -71,9 +72,11 @@
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemLanguage}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
Width="250" />
<ComboBox
SelectedIndex="{Binding Language}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
@@ -138,6 +141,7 @@
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemTimeZone}"
ToolTip.Tip="{ext:Locale TimezoneTooltip}"
Width="250" />
<AutoCompleteBox
Name="TimeZoneBox"
@@ -148,6 +152,7 @@
SelectionChanged="TimeZoneBox_OnSelectionChanged"
Text="{Binding Path=TimeZone, Mode=OneWay}"
TextChanged="TimeZoneBox_OnTextChanged"
ToolTip.Tip="{ext:Locale TimezoneTooltip}"
ValueMemberBinding="{Binding Mode=OneWay, Converter={x:Static helpers:TimeZoneConverter.Instance}}" />
</StackPanel>
<StackPanel
@@ -158,11 +163,13 @@
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemTime}"
ToolTip.Tip="{ext:Locale TimeTooltip}"
Width="250"/>
<DatePicker
VerticalAlignment="Center"
IsEnabled="{Binding !MatchSystemTime}"
SelectedDate="{Binding CurrentDate}"
ToolTip.Tip="{ext:Locale TimeTooltip}"
Width="350" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel>
@@ -176,7 +183,8 @@
ClockIdentifier="24HourClock"
IsEnabled="{Binding !MatchSystemTime}"
SelectedTime="{Binding CurrentTime}"
Width="350" />
Width="350"
ToolTip.Tip="{ext:Locale TimeTooltip}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel>
<StackPanel
@@ -281,7 +289,6 @@
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemDramSize}"
ToolTip.Tip="{ext:Locale DRamTooltip}"
Width="250" />
<ComboBox
SelectedIndex="{Binding DramSize}"