Compare commits

..

2 Commits

Author SHA1 Message Date
Max
5566e752a4 [HID] Restructure HD Rumble class for future controller support (#109)
- Attempted fixing the strength: so far it hasn't been successful.
- Rumble should skip vibrations if they're not in-line with poll-rate: would like to come back to this. Queuing just does exactly what the hid buffer does, but our timer (poll rate) is not in sync with the rate the controller is reading at, which causes excess drops.
- Refactored the class so that implementing support for HD rumble for other controllers (DS5, Steam Controller) is much easier in the future.

Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/109
2026-06-26 05:11:19 +00:00
awesomeangotti
a5f72136b2 UI: Add random splashes to loading screen (#128)
This PR introduces splash text messages that change per startup on the loading screen after selecting a game. It also moves the "RYUBING" logo splash in logs to be inside its own class, which also handles loading screen splashes and titlebar splashes. Credits to VewDev, Lotp, Sh0inx, yell0wsuit, and Greemdev for pointers and assistance throughout this PR.

Co-authored-by: Awesomeangotti <awesomeangotti@noreply.git.ryujinx.app>
Co-authored-by: Awesomeangotti <143439211+Awesomeangotti@users.noreply.github.com>
Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/128
2026-06-26 02:42:41 +00:00
12 changed files with 356 additions and 99 deletions

View File

@@ -9606,7 +9606,7 @@
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Sends more data to the controller for better rumble.\n\nCurrently only supports first-party Nintendo Switch controllers.\n\nLeave ON if you're using JoyCons or a Pro Controller.",
"en_US": "EXPERIMENTAL.\n\nSends more data to the controller for better rumble.\n\nCurrently only supports first-party Nintendo Switch controllers.\n\nLeave OFF if unsure.",
"es_ES": "",
"fr_FR": "",
"he_IL": "",

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
private readonly bool[] _supportedPlayers;
private VibrationValue _neutralVibrationValue = new()
{
AmplitudeLow = 0f,
AmplitudeLow = 0.01f,
FrequencyLow = 160f,
AmplitudeHigh = 0f,
FrequencyHigh = 320f,

View File

@@ -13,84 +13,98 @@ namespace Ryujinx.Input.SDL3
{
private readonly SDL_hid_device* _hidHandle;
private byte[] _buffer;
private static ushort _vendor;
private static ushort _product;
private int _globalCount;
private ulong _lastWriteTicks;
private NpadHdRumble(SDL_hid_device* hidHandle)
{
_hidHandle = hidHandle;
InitializeDevice();
}
public static NpadHdRumble Create(SDL_Gamepad* gamepadHandle)
{
ushort vendor = SDL_GetGamepadVendor(gamepadHandle);
if (vendor != 0x057e)
_vendor = SDL_GetGamepadVendor(gamepadHandle);
if (!Enum.IsDefined(typeof(HDRumbleSupportedVendor), _vendor))
{
return null;
}
ushort product = SDL_GetGamepadProduct(gamepadHandle);
if (!Enum.IsDefined(typeof(HDRumbleSupported), product))
_product = SDL_GetGamepadProduct(gamepadHandle);
if (!Enum.IsDefined(typeof(HDRumbleSupportedProduct), _product))
{
return null;
}
return new NpadHdRumble(SDL_hid_open(vendor, product, 0));
int serialNumber = 0;
string? serial = SDL_GetGamepadSerial(gamepadHandle);
if (serial is not null)
{
int.TryParse(serial, out serialNumber);
}
return new NpadHdRumble(SDL_hid_open(_vendor, _product, serialNumber));
}
// Some of the code was translated from https://github.com/MIZUSHIKI/JoyShockLibrary-plus-HDRumble
private bool WriteHdRumble(
int encLeftLowFreq, int encLeftLowAmp,
int encLeftHighFreq, int encLeftHighAmp,
int encRightLowFreq, int encRightLowAmp,
int encRightHighFreq, int encRightHighAmp)
private bool WriteNintendoHdRumble(VibrationValue left, VibrationValue right)
{
byte[] buf = new byte[10];
buf[0] = 0x10;
buf[1] = (byte)((++_globalCount) & 0xF);
buf[2] = (byte)(encLeftHighFreq & 0xFF);
buf[3] = (byte)(encLeftHighAmp + ((encLeftHighFreq >> 8) & 0xFF));
buf[4] = (byte)(encLeftLowFreq + ((encLeftLowAmp >> 8) & 0xFF));
buf[5] = (byte)(encLeftLowAmp & 0xFF);
buf[6] = (byte)(encRightHighFreq & 0xFF);
buf[7] = (byte)(encRightHighAmp + ((encRightHighFreq >> 8) & 0xFF));
buf[8] = (byte)(encRightLowFreq + ((encRightLowAmp >> 8) & 0xFF));
buf[9] = (byte)(encRightLowAmp & 0xFF);
int leftLowAmp = EncodeLowAmp(left.AmplitudeLow);
int leftLowFreq = EncodeLowFreq(left.FrequencyLow) + (leftLowAmp >> 8);
int leftHighFreq = EncodeHighFreq(left.FrequencyHigh);
int leftHighAmp = EncodeHighAmp(left.AmplitudeHigh) + (leftHighFreq >> 8);
int rightLowAmp = EncodeLowAmp(right.AmplitudeLow);
int rightLowFreq = EncodeLowFreq(right.FrequencyLow) + (rightLowAmp >> 8);
int rightHighFreq = EncodeHighFreq(right.FrequencyHigh);
int rightHighAmp = EncodeHighAmp(right.AmplitudeHigh) + (rightHighFreq >> 8);
_buffer[0] = 0x10;
_buffer[1] = (byte)((_globalCount++) & 0xF);
// Left LRA
_buffer[2] = (byte)(leftLowFreq & 0xFF);
_buffer[3] = (byte)(leftHighAmp & 0xFF);
_buffer[4] = (byte)(leftHighFreq & 0xFF);
_buffer[5] = (byte)(leftLowAmp & 0xFF);
// Right LRA
_buffer[6] = (byte)(rightLowFreq & 0xFF);
_buffer[7] = (byte)(rightHighAmp & 0xFF);
_buffer[8] = (byte)(rightHighFreq & 0xFF);
_buffer[9] = (byte)(rightLowAmp & 0xFF);
if (_globalCount > 0xF)
{
_globalCount = 0x0;
}
fixed (byte* ptr = buf)
fixed (byte* ptr = _buffer)
{
if (SendHDRumble(ptr, (nuint)buf.Length) >= 0)
if (SendHdRumble(ptr, (nuint)_buffer.Length) >= 0)
{
return true;
}
if (!String.IsNullOrEmpty(SDL_GetError()))
{
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
SDL_ClearError();
}
return false;
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
SDL_ClearError();
}
return false;
}
private static int EncodeLowFreq(float lowFreq)
{
float lf = Math.Clamp(lowFreq, 40.875885f, 626.286133f);
return (int) Math.Round(32 * Math.Log2(lf * 0.1f) - 0x40);
return (int)Math.Clamp(32 * Math.Log2(lowFreq * 0.1f) - 0x40, 81.75177f, 1252.572266f);
}
private static int EncodeHighFreq(float highFreq)
{
float hf = Math.Clamp(highFreq, 81.75177f, 1252.572266f);
return (int) Math.Round((32 * Math.Log2(hf * 0.1f) - 0x60) * 4);
return (int)Math.Clamp(32 * Math.Log2(highFreq * 0.1f) - 0x60, 81.75177f, 1252.572266f);
}
private static int EncodeLowAmp(float rawAmp)
@@ -98,23 +112,20 @@ namespace Ryujinx.Input.SDL3
double encodedAmp = 0;
if (rawAmp is > 0 and < 0.012f)
{
encodedAmp = 1;
}
else if (rawAmp is >= 0.012f and < 0.112f)
{
encodedAmp = 4 * Math.Log2(rawAmp * 110f);
}
else if (rawAmp is >= 0.112f and < 0.225f)
{
encodedAmp = 16 * Math.Log2(rawAmp * 17f);
}
else if (rawAmp is >= 0.225f and <= 1f)
{
encodedAmp = 32 * Math.Log2(rawAmp * 8.7f);
}
return (int)Math.Floor(encodedAmp / 2.0) + 64;
encodedAmp = Math.Round((encodedAmp / 2.0) + 64.0);
encodedAmp = Math.Clamp(encodedAmp, 0.0, 100.2867);
return (int)Math.Round(encodedAmp);
}
private static int EncodeHighAmp(float rawAmp)
@@ -122,82 +133,156 @@ namespace Ryujinx.Input.SDL3
double encodedAmp = 0;
if (rawAmp is > 0 and < 0.012f)
{
encodedAmp = 1;
}
else if (rawAmp is >= 0.012f and < 0.112f)
{
encodedAmp = 4 * Math.Log2(rawAmp * 110f);
}
else if (rawAmp is >= 0.112f and < 0.225f)
{
encodedAmp = 16 * Math.Log2(rawAmp * 17f);
}
else if (rawAmp is >= 0.225f and <= 1f)
{
encodedAmp = 32 * Math.Log2(rawAmp * 8.7f);
}
return (int) Math.Round(encodedAmp * 2);
encodedAmp = Math.Round(encodedAmp / 2.0);
encodedAmp = Math.Clamp(encodedAmp, 0.0, 100.2867);
return (int)encodedAmp;
}
public bool HdRumble(VibrationValue left, VibrationValue right)
{
return WriteHdRumble(EncodeLowFreq(left.FrequencyLow),
EncodeLowAmp(left.AmplitudeLow),
EncodeHighFreq(left.FrequencyHigh),
EncodeHighAmp(left.AmplitudeHigh),
EncodeLowFreq(right.FrequencyLow),
EncodeLowAmp(right.AmplitudeLow),
EncodeHighFreq(right.FrequencyHigh),
EncodeHighAmp(right.AmplitudeHigh));
if(_product is (ushort) HDRumbleSupportedProduct.ProController
or (ushort) HDRumbleSupportedProduct.JoyconLeft
or (ushort) HDRumbleSupportedProduct.JoyconRight
or (ushort) HDRumbleSupportedProduct.JoyconPair
or (ushort) HDRumbleSupportedProduct.JoyconGrip)
{
return WriteNintendoHdRumble(left, right);
}
return false;
}
private int SendHDRumble(byte* data, nuint length)
private int SendHdRumble(byte* data, nuint length)
{
int result = 0;
ulong currentTicks = SDL_GetTicks();
// Ditch rumble if we haven't hit the poll-rate yet.
// TODO: figure out a better way to do this
// While the polling check makes the rumble accurate, it also causes it to miss signals.
if ((currentTicks - _lastWriteTicks) < 8) // https://docs.handheldlegend.com/s/progcc-3/doc/lag-comparison-aAR1mV3JLX
if ((currentTicks - _lastWriteTicks) <= GetPollRate())
{
return result;
}
SDL_LockJoysticks();
result = SDL_hid_write(_hidHandle, data, length);
if (result >= 0)
{
// Fun fact: Mario Kart 8 Deluxe sends rumble packets
// where the amplitude is zero, but the frequency isn't.
result = SDL_hid_write(_hidHandle, data, length);
if (result >= 0)
{
_lastWriteTicks = currentTicks;
}
_lastWriteTicks = currentTicks;
}
SDL_UnlockJoysticks();
return result;
}
private void InitializeDevice()
{
if (_vendor is (ushort)HDRumbleSupportedVendor.Nintendo)
{
_buffer = new byte[10];
byte[] init = new byte[64];
// Pro Controller and Charge Grip
if (_product
is (ushort)HDRumbleSupportedProduct.ProController
or (ushort)HDRumbleSupportedProduct.JoyconGrip)
{
SDL_LockJoysticks();
fixed (byte* ptr = init)
{
init[0] = 0x80;
init[1] = 0x05; // Allow bluetooth timeout TODO: use 0x04 to force USB only (toggle?)
SDL_hid_write(_hidHandle, ptr, 64);
}
SDL_UnlockJoysticks();
return;
}
// Joycons
if (_product
is (ushort)HDRumbleSupportedProduct.JoyconLeft
or (ushort)HDRumbleSupportedProduct.JoyconRight
or (ushort)HDRumbleSupportedProduct.JoyconPair)
{
SDL_LockJoysticks();
fixed (byte* ptr = init)
{
// we could write data to the controller here (see above)
}
SDL_UnlockJoysticks();
return;
}
}
}
private ulong GetPollRate()
{
ulong pollRate = 0;
if (_vendor is (ushort)HDRumbleSupportedVendor.Nintendo)
{
// https://docs.handheldlegend.com/s/progcc-3/doc/lag-comparison-aAR1mV3JLX
pollRate = (ulong) 16.67;
if (_product is (ushort)HDRumbleSupportedProduct.ProController
&& SDL_hid_get_device_info(_hidHandle)->bus_type == SDL_hid_bus_type.SDL_HID_API_BUS_USB)
{
pollRate = (ulong) 8.33;
}
}
return pollRate;
}
public void Dispose()
{
GC.SuppressFinalize(this);
SDL_hid_close(_hidHandle);
}
}
public enum HDRumbleSupported : ushort
public enum HDRumbleSupportedVendor : ushort
{
JoyConLeft = 0x2006,
JoyConRight = 0x2007,
Nintendo = 0x057e,
Valve = 0x28de,
Sony = 0x054c
}
public enum HDRumbleSupportedProduct : ushort
{
// TODO: Currently, HD Rumble only supports the Pro Controller and JoyCons.
// We need to initialize and report to each device differently.
// Nintendo Switch: 0x057e
JoyconLeft = 0x2006,
JoyconRight = 0x2007,
JoyconPair = 0x2008,
ProController = 0x2009,
JoyconGrip = 0x200e,
// Nintendo Switch 2: 0x057e
Joycon2Right = 0x2066,
Joycon2Left = 0x2067,
Joycon2Pair = 0x2068,
Switch2ProController = 0x2069,
GamecubeController = 0x2073
GamecubeController = 0x2073,
// Valve Steam Family: 0x28de
// https://github.com/libsdl-org/SDL/issues/9148
SteamDeck = 0x11ff,
SteamDeckVirtualDevice = 0x1205,
SteamController = 0x1106,
// PlayStation Dualsense: 0x054c
Dualsense = 0x0ce6
}
}

View File

@@ -582,12 +582,12 @@ namespace Ryujinx.Input.HLE
Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " +
// Value=value/multiplier * multiplier (result)
$"L.low.amp={leftVibrationValue.AmplitudeLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeLow}), " +
$"L.high.amp={leftVibrationValue.AmplitudeHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeHigh}), " +
$"L.high.amp={leftVibrationValue.AmplitudeHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({leftVibrationValue.AmplitudeHigh}), " +
$"L.low.freq={leftVibrationValue.FrequencyLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyLow}), " +
$"L.high.freq={leftVibrationValue.FrequencyHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyHigh}), " +
$"R.low.amp={rightVibrationValue.AmplitudeLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeLow}), " +
$"L.high.freq={leftVibrationValue.FrequencyHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({leftVibrationValue.FrequencyHigh}), " +
$"R.low.amp={rightVibrationValue.AmplitudeLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({rightVibrationValue.AmplitudeLow}), " +
$"R.high.amp={rightVibrationValue.AmplitudeHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeHigh}), " +
$"R.low.freq={rightVibrationValue.FrequencyLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyLow}), " +
$"R.low.freq={rightVibrationValue.FrequencyLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({rightVibrationValue.FrequencyLow}), " +
$"R.high.freq={rightVibrationValue.FrequencyHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyHigh})");
}
}

View File

@@ -140,7 +140,7 @@ namespace Ryujinx.Input
StrongRumble = 1f,
WeakRumble = 1f,
EnableRumble = false,
UseHDRumble = true,
UseHDRumble = false
},
};
}

View File

@@ -0,0 +1,98 @@
{
"Locales": {
"ar_SA": [],
"de_DE": [],
"el_GR": [],
"en_US": [
"Ryubing is my middle name.",
"Giving it 110 percent!",
"I don't think therefore I don't am!",
"All hail Egg.",
"Insert cringy joke here.",
"ITS RYUBINGING TIME!",
"I hate Mondays...",
"Fantastical!",
"Now with 100% more humor!",
"'Not S&P approved' has been approved by S&P.",
"ARE YOU NOT ENTERTAINED?",
"It's an emulator!",
"Now the real game begins...",
"Cooked fresh since 2018!",
"Must've been the wind...",
"I used to be an adventurer like you before I took an arrow to the knee.",
"Ryubing!",
"May contain nuts!",
"May include occasional pop culture references!",
"100% organically grown!",
"Have a nice day : )",
"Spoats car!",
"Bottom text",
"Im sorry Dave. I'm afraid I can't do that.",
"That's no moon...",
"Sir, finishing this fight.",
"I see how it is...",
"Space! The final frontier!",
"If you could not tell already, I love making bad jokes : )",
"this.",
"Probably contains no baked beans.",
"Y'all ready for this?",
"Removed Herobrine.",
"Right to repair!",
"Programmed in C#!",
"Forgejo has dethroned Gitlab!",
"Any ideas what to put here?",
"Good morning!",
"Good afternoon!",
"Good evening!",
"I hope you are having a great day!",
"Please insert disc two!",
"I... AM RYUBING!",
"Ryubingin' it up",
"bing bing wahoo.",
"egg",
"No, lossless scaling is NOT supported.",
"How do you people do anything?",
"One dollar.",
"Somebody once told me!",
"Its that time of the year again!",
"Brewed from only the finest memes.",
"Async shader compilation would destroy my soul : (",
"Trans rights are human rights!",
":3",
"Patched ':3' splash replication glitch.",
"Please connect a controller!",
"Never gonna give you up!",
"The game was rigged from the start.",
"Ganon is watching you!",
"Now with 100% more JSON in the splash code!",
"Countless hours of fun!",
"Sorry, Link. I can't give credit. Come back when you're a little... mmmmmm... richer!",
"Do a barrel roll!",
"You've met with a terrible fate, haven't you?",
"Yahaha! You found me!",
"I would've been in real trouble if you hadn't shown up when you did, goro.",
"Stay fresh!",
"Yellow, black. Yellow, black. Yellow, black. Yellow, black. Ooh, black and yellow! Let's shake it up a little.",
"Whaaa? You came to see me again? That makes Beedle SO HAPPY!",
"Don't get cooked, stay off the hook!",
"Now with 100% more good vibes in the splash code!",
"It is Wednesday my dudes!"
],
"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": []
}
}

View File

@@ -0,0 +1,64 @@
using System.Collections.Generic;
using Ryujinx.Common.Logging;
using Gommon;
using Ryujinx.Ava.Systems.Configuration;
using System;
using System.Text.Json;
namespace Ryujinx.Common
{
public class SplashTextHelper
{
public static void PrintSplash()
{
Logger.Notice.Print(LogClass.Application, " ___ __ _ ");
Logger.Notice.Print(LogClass.Application, @" / _ \ __ __ __ __ / / (_) ___ ___ _");
Logger.Notice.Print(LogClass.Application, @" / , _/ / // // // / / _ \ / / / _ \ / _ `/");
Logger.Notice.Print(LogClass.Application, @"/_/|_| \_, / \_,_/ /_.__//_/ /_//_/ \_, / ");
Logger.Notice.Print(LogClass.Application, " /___/ /___/ ");
Logger.Notice.Print(LogClass.Application, "");
Logger.Notice.Print(LogClass.Application, GetSplash());
Logger.Notice.Print(LogClass.Application, "");
}
private static string s_finalSplash = "";
public static string GetSplash()
{
if (string.IsNullOrEmpty(s_finalSplash))
{
s_finalSplash = GetLangJson();
if (string.IsNullOrEmpty(s_finalSplash))
{
s_finalSplash = "Splash Text";
}
}
return $"{s_finalSplash}";
}
private static SplashLocales s_splashJson;
private static string GetLangJson()
{
try
{
string data;
data = EmbeddedResources.ReadAllText("Ryujinx/Assets/Splashes.json");
s_splashJson = JsonSerializer.Deserialize<SplashLocales>(data);
return s_splashJson.Locales[ConfigurationState.Instance.UI.LanguageCode.Value].GetRandomElement();
}
catch
{
return "";
}
}
private struct SplashLocales
{
public Dictionary<string, List<string>> Locales { get; set; }
}
}
}

View File

@@ -437,13 +437,9 @@ namespace Ryujinx.Ava
internal static void PrintSystemInfo()
{
Logger.Notice.Print(LogClass.Application, " ___ __ _ ");
Logger.Notice.Print(LogClass.Application, @" / _ \ __ __ __ __ / / (_) ___ ___ _");
Logger.Notice.Print(LogClass.Application, @" / , _/ / // // // / / _ \ / / / _ \ / _ `/");
Logger.Notice.Print(LogClass.Application, @"/_/|_| \_, / \_,_/ /_.__//_/ /_//_/ \_, / ");
Logger.Notice.Print(LogClass.Application, " /___/ /___/ ");
// Print the ryubing logo + joke splash
SplashTextHelper.PrintSplash();
Logger.Notice.Print(LogClass.Application, $"{RyujinxApp.FullAppName} Version: {Version}");
Logger.Notice.Print(LogClass.Application, $".NET Runtime: {RuntimeInformation.FrameworkDescription}");
SystemInfo.Gather().Print();

View File

@@ -176,6 +176,7 @@
<EmbeddedResource Include="Assets\UIImages\Logo_Forgejo.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
<EmbeddedResource Include="Assets\PlayReports\*.json" />
<EmbeddedResource Include="Assets\Splashes.json" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\assets\Locales\*.json" />

View File

@@ -336,7 +336,7 @@ namespace Ryujinx.Ava.Systems.Configuration
EnableRumble = false,
StrongRumble = 1f,
WeakRumble = 1f,
UseHDRumble = true
UseHDRumble = false
};
}
}

View File

@@ -76,6 +76,8 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] public partial string LoadHeading { get; set; }
[ObservableProperty] public partial string CacheLoadStatus { get; set; }
[ObservableProperty] public partial string Splash { get; set; }
[ObservableProperty] public partial string DockedStatusText { get; set; }
@@ -1256,6 +1258,7 @@ namespace Ryujinx.Ava.UI.ViewModels
break;
case ShaderCacheLoadingState shaderCacheState:
CacheLoadStatus = $"{current} / {total}";
Splash = $"\"{SplashTextHelper.GetSplash()}\"";
switch (shaderCacheState)
{
case ShaderCacheLoadingState.Start:

View File

@@ -135,7 +135,7 @@
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
IsVisible="{Binding ShowLoadProgress}" RowDefinitions="Auto,Auto,Auto">
IsVisible="{Binding ShowLoadProgress}" RowDefinitions="Auto,Auto,Auto,Auto">
<TextBlock
Grid.Row="0"
Margin="10"
@@ -179,6 +179,16 @@
Text="{Binding CacheLoadStatus}"
TextAlignment="Start"
MaxWidth="500" />
<TextBlock
Grid.Row="3"
Margin="10"
FontSize="14"
FontStyle="Oblique"
IsVisible="{Binding ShowLoadProgress}"
Text="{Binding Splash}"
Foreground="LightGray"
TextAlignment="Start"
MaxWidth="500" />
</Grid>
</Grid>
</Grid>