mirror of
https://github.com/GreemDev/Ryujinx.git
synced 2024-12-22 19:15:47 +00:00
Add the Cabinet Applet (#340)
This adds the missing Cabinet Applet, which allows for formatting Amiibos and changing their names.
This commit is contained in:
parent
17483aad24
commit
08b7257be5
24 changed files with 335 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Applets.Browser;
|
using Ryujinx.HLE.HOS.Applets.Browser;
|
||||||
|
using Ryujinx.HLE.HOS.Applets.Cabinet;
|
||||||
using Ryujinx.HLE.HOS.Applets.Dummy;
|
using Ryujinx.HLE.HOS.Applets.Dummy;
|
||||||
using Ryujinx.HLE.HOS.Applets.Error;
|
using Ryujinx.HLE.HOS.Applets.Error;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||||
|
@ -31,6 +32,8 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
case AppletId.MiiEdit:
|
case AppletId.MiiEdit:
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet");
|
Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet");
|
||||||
return new DummyApplet(system);
|
return new DummyApplet(system);
|
||||||
|
case AppletId.Cabinet:
|
||||||
|
return new CabinetApplet(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Applet {applet} not implemented!");
|
Logger.Warning?.Print(LogClass.Application, $"Applet {applet} not implemented!");
|
||||||
|
|
195
src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs
Normal file
195
src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Nfc.Nfp;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Applets.Cabinet
|
||||||
|
{
|
||||||
|
internal unsafe class CabinetApplet : IApplet
|
||||||
|
{
|
||||||
|
private readonly Horizon _system;
|
||||||
|
private AppletSession _normalSession;
|
||||||
|
|
||||||
|
public event EventHandler AppletStateChanged;
|
||||||
|
|
||||||
|
public CabinetApplet(Horizon system)
|
||||||
|
{
|
||||||
|
_system = system;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
|
||||||
|
{
|
||||||
|
_normalSession = normalSession;
|
||||||
|
|
||||||
|
byte[] launchParams = _normalSession.Pop();
|
||||||
|
byte[] startParamBytes = _normalSession.Pop();
|
||||||
|
|
||||||
|
StartParamForAmiiboSettings startParam = IApplet.ReadStruct<StartParamForAmiiboSettings>(startParamBytes);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm, $"CabinetApplet Start Type: {startParam.Type}");
|
||||||
|
|
||||||
|
switch (startParam.Type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
StartNicknameAndOwnerSettings(ref startParam);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
StartFormatter(ref startParam);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Logger.Error?.Print(LogClass.ServiceAm, $"Unknown AmiiboSettings type: {startParam.Type}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the response
|
||||||
|
ReturnValueForAmiiboSettings returnValue = new()
|
||||||
|
{
|
||||||
|
AmiiboSettingsReturnFlag = (byte)AmiiboSettingsReturnFlag.HasRegisterInfo,
|
||||||
|
DeviceHandle = new DeviceHandle
|
||||||
|
{
|
||||||
|
Handle = 0 // Dummy device handle
|
||||||
|
},
|
||||||
|
RegisterInfo = startParam.RegisterInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
// Push the response
|
||||||
|
_normalSession.Push(BuildResponse(returnValue));
|
||||||
|
AppletStateChanged?.Invoke(this, null);
|
||||||
|
|
||||||
|
_system.ReturnFocus();
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultCode GetResult()
|
||||||
|
{
|
||||||
|
_system.Device.System.NfpDevices.RemoveAt(0);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartFormatter(ref StartParamForAmiiboSettings startParam)
|
||||||
|
{
|
||||||
|
// Initialize RegisterInfo
|
||||||
|
startParam.RegisterInfo = new RegisterInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartNicknameAndOwnerSettings(ref StartParamForAmiiboSettings startParam)
|
||||||
|
{
|
||||||
|
_system.Device.UIHandler.DisplayCabinetDialog(out string newName);
|
||||||
|
byte[] nameBytes = Encoding.UTF8.GetBytes(newName);
|
||||||
|
Array41<byte> nickName = new Array41<byte>();
|
||||||
|
nameBytes.CopyTo(nickName.AsSpan());
|
||||||
|
startParam.RegisterInfo.Nickname = nickName;
|
||||||
|
NfpDevice devicePlayer1 = new()
|
||||||
|
{
|
||||||
|
NpadIdType = NpadIdType.Player1,
|
||||||
|
Handle = HidUtils.GetIndexFromNpadIdType(NpadIdType.Player1),
|
||||||
|
State = NfpDeviceState.SearchingForTag,
|
||||||
|
};
|
||||||
|
_system.Device.System.NfpDevices.Add(devicePlayer1);
|
||||||
|
_system.Device.UIHandler.DisplayCabinetMessageDialog();
|
||||||
|
string amiiboId = string.Empty;
|
||||||
|
bool scanned = false;
|
||||||
|
while (!scanned)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _system.Device.System.NfpDevices.Count; i++)
|
||||||
|
{
|
||||||
|
if (_system.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound)
|
||||||
|
{
|
||||||
|
amiiboId = _system.Device.System.NfpDevices[i].AmiiboId;
|
||||||
|
scanned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VirtualAmiibo.UpdateNickName(amiiboId, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] BuildResponse(ReturnValueForAmiiboSettings returnValue)
|
||||||
|
{
|
||||||
|
int size = Unsafe.SizeOf<ReturnValueForAmiiboSettings>();
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
|
||||||
|
fixed (byte* bytesPtr = bytes)
|
||||||
|
{
|
||||||
|
Unsafe.Write(bytesPtr, returnValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T ReadStruct<T>(byte[] data) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (data.Length < Unsafe.SizeOf<T>())
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Not enough data to read the struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed (byte* dataPtr = data)
|
||||||
|
{
|
||||||
|
return Unsafe.Read<T>(dataPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Structs
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public unsafe struct TagInfo
|
||||||
|
{
|
||||||
|
public fixed byte Data[0x58];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public unsafe struct StartParamForAmiiboSettings
|
||||||
|
{
|
||||||
|
public byte ZeroValue; // Left at zero by sdknso
|
||||||
|
public byte Type;
|
||||||
|
public byte Flags;
|
||||||
|
public byte AmiiboSettingsStartParamOffset28;
|
||||||
|
public ulong AmiiboSettingsStartParam0;
|
||||||
|
|
||||||
|
public TagInfo TagInfo; // Only enabled when flags bit 1 is set
|
||||||
|
public RegisterInfo RegisterInfo; // Only enabled when flags bit 2 is set
|
||||||
|
|
||||||
|
public fixed byte StartParamExtraData[0x20];
|
||||||
|
|
||||||
|
public fixed byte Reserved[0x24];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public unsafe struct ReturnValueForAmiiboSettings
|
||||||
|
{
|
||||||
|
public byte AmiiboSettingsReturnFlag;
|
||||||
|
private byte Padding1;
|
||||||
|
private byte Padding2;
|
||||||
|
private byte Padding3;
|
||||||
|
public DeviceHandle DeviceHandle;
|
||||||
|
public TagInfo TagInfo;
|
||||||
|
public RegisterInfo RegisterInfo;
|
||||||
|
public fixed byte IgnoredBySdknso[0x24];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public struct DeviceHandle
|
||||||
|
{
|
||||||
|
public ulong Handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AmiiboSettingsReturnFlag : byte
|
||||||
|
{
|
||||||
|
Cancel = 0,
|
||||||
|
HasTagInfo = 2,
|
||||||
|
HasRegisterInfo = 4,
|
||||||
|
HasTagInfoAndRegisterInfo = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -93,6 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||||
return registerInfo;
|
return registerInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void UpdateNickName(string amiiboId, string newNickName)
|
||||||
|
{
|
||||||
|
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||||
|
virtualAmiiboFile.NickName = newNickName;
|
||||||
|
SaveAmiiboFile(virtualAmiiboFile);
|
||||||
|
}
|
||||||
|
|
||||||
public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
|
public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
|
||||||
{
|
{
|
||||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||||
|
|
|
@ -24,6 +24,18 @@ namespace Ryujinx.HLE.UI
|
||||||
/// <returns>True when OK is pressed, False otherwise.</returns>
|
/// <returns>True when OK is pressed, False otherwise.</returns>
|
||||||
bool DisplayMessageDialog(ControllerAppletUIArgs args);
|
bool DisplayMessageDialog(ControllerAppletUIArgs args);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Displays an Input Dialog box to the user so they can enter the Amiibo's new name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userText">Text that the user entered. Set to `null` on internal errors</param>
|
||||||
|
/// <returns>True when OK is pressed, False otherwise. Also returns True on internal errors</returns>
|
||||||
|
bool DisplayCabinetDialog(out string userText);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Displays a Message Dialog box to the user to notify them to scan the Amiibo.
|
||||||
|
/// </summary>
|
||||||
|
void DisplayCabinetMessageDialog();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tell the UI that we need to transition to another program.
|
/// Tell the UI that we need to transition to another program.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
|
using LibHac.Tools.Fs;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
@ -485,6 +486,19 @@ namespace Ryujinx.Headless.SDL2
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DisplayCabinetDialog(out string userText)
|
||||||
|
{
|
||||||
|
// SDL2 doesn't support input dialogs
|
||||||
|
userText = "Ryujinx";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayCabinetMessageDialog()
|
||||||
|
{
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog", "Please scan your Amiibo now.", WindowHandle);
|
||||||
|
}
|
||||||
|
|
||||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||||
{
|
{
|
||||||
if (_ignoreControllerApplet) return false;
|
if (_ignoreControllerApplet) return false;
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "مطلقا",
|
"Never": "مطلقا",
|
||||||
"SwkbdMinCharacters": "يجب أن يبلغ طوله {0} حرفا على الأقل",
|
"SwkbdMinCharacters": "يجب أن يبلغ طوله {0} حرفا على الأقل",
|
||||||
"SwkbdMinRangeCharacters": "يجب أن يتكون من {0}-{1} حرفا",
|
"SwkbdMinRangeCharacters": "يجب أن يتكون من {0}-{1} حرفا",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "لوحة المفاتيح البرمجية",
|
"SoftwareKeyboard": "لوحة المفاتيح البرمجية",
|
||||||
"SoftwareKeyboardModeNumeric": "يجب أن يكون 0-9 أو '.' فقط",
|
"SoftwareKeyboardModeNumeric": "يجب أن يكون 0-9 أو '.' فقط",
|
||||||
"SoftwareKeyboardModeAlphabet": "يجب أن تكون الأحرف غير CJK فقط",
|
"SoftwareKeyboardModeAlphabet": "يجب أن تكون الأحرف غير CJK فقط",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Niemals",
|
"Never": "Niemals",
|
||||||
"SwkbdMinCharacters": "Muss mindestens {0} Zeichen lang sein",
|
"SwkbdMinCharacters": "Muss mindestens {0} Zeichen lang sein",
|
||||||
"SwkbdMinRangeCharacters": "Muss {0}-{1} Zeichen lang sein",
|
"SwkbdMinRangeCharacters": "Muss {0}-{1} Zeichen lang sein",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Software-Tastatur",
|
"SoftwareKeyboard": "Software-Tastatur",
|
||||||
"SoftwareKeyboardModeNumeric": "Darf nur 0-9 oder \".\" sein",
|
"SoftwareKeyboardModeNumeric": "Darf nur 0-9 oder \".\" sein",
|
||||||
"SoftwareKeyboardModeAlphabet": "Keine CJK-Zeichen",
|
"SoftwareKeyboardModeAlphabet": "Keine CJK-Zeichen",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Ποτέ",
|
"Never": "Ποτέ",
|
||||||
"SwkbdMinCharacters": "Πρέπει να έχει μήκος τουλάχιστον {0} χαρακτήρες",
|
"SwkbdMinCharacters": "Πρέπει να έχει μήκος τουλάχιστον {0} χαρακτήρες",
|
||||||
"SwkbdMinRangeCharacters": "Πρέπει να έχει μήκος {0}-{1} χαρακτήρες",
|
"SwkbdMinRangeCharacters": "Πρέπει να έχει μήκος {0}-{1} χαρακτήρες",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Εικονικό Πληκτρολόγιο",
|
"SoftwareKeyboard": "Εικονικό Πληκτρολόγιο",
|
||||||
"SoftwareKeyboardModeNumeric": "Πρέπει να είναι 0-9 ή '.' μόνο",
|
"SoftwareKeyboardModeNumeric": "Πρέπει να είναι 0-9 ή '.' μόνο",
|
||||||
"SoftwareKeyboardModeAlphabet": "Πρέπει να μην είναι μόνο χαρακτήρες CJK",
|
"SoftwareKeyboardModeAlphabet": "Πρέπει να μην είναι μόνο χαρακτήρες CJK",
|
||||||
|
|
|
@ -714,6 +714,9 @@
|
||||||
"Never": "Never",
|
"Never": "Never",
|
||||||
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
||||||
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Software Keyboard",
|
"SoftwareKeyboard": "Software Keyboard",
|
||||||
"SoftwareKeyboardModeNumeric": "Must be 0-9 or '.' only",
|
"SoftwareKeyboardModeNumeric": "Must be 0-9 or '.' only",
|
||||||
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
|
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Nunca",
|
"Never": "Nunca",
|
||||||
"SwkbdMinCharacters": "Debe tener al menos {0} caracteres",
|
"SwkbdMinCharacters": "Debe tener al menos {0} caracteres",
|
||||||
"SwkbdMinRangeCharacters": "Debe tener {0}-{1} caracteres",
|
"SwkbdMinRangeCharacters": "Debe tener {0}-{1} caracteres",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Teclado de software",
|
"SoftwareKeyboard": "Teclado de software",
|
||||||
"SoftwareKeyboardModeNumeric": "Debe ser sólo 0-9 o '.'",
|
"SoftwareKeyboardModeNumeric": "Debe ser sólo 0-9 o '.'",
|
||||||
"SoftwareKeyboardModeAlphabet": "Solo deben ser caracteres no CJK",
|
"SoftwareKeyboardModeAlphabet": "Solo deben ser caracteres no CJK",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Jamais",
|
"Never": "Jamais",
|
||||||
"SwkbdMinCharacters": "Doit comporter au moins {0} caractères",
|
"SwkbdMinCharacters": "Doit comporter au moins {0} caractères",
|
||||||
"SwkbdMinRangeCharacters": "Doit comporter entre {0} et {1} caractères",
|
"SwkbdMinRangeCharacters": "Doit comporter entre {0} et {1} caractères",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Clavier logiciel",
|
"SoftwareKeyboard": "Clavier logiciel",
|
||||||
"SoftwareKeyboardModeNumeric": "Doit être 0-9 ou '.' uniquement",
|
"SoftwareKeyboardModeNumeric": "Doit être 0-9 ou '.' uniquement",
|
||||||
"SoftwareKeyboardModeAlphabet": "Doit être uniquement des caractères non CJK",
|
"SoftwareKeyboardModeAlphabet": "Doit être uniquement des caractères non CJK",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "אף פעם",
|
"Never": "אף פעם",
|
||||||
"SwkbdMinCharacters": "לפחות {0} תווים",
|
"SwkbdMinCharacters": "לפחות {0} תווים",
|
||||||
"SwkbdMinRangeCharacters": "באורך {0}-{1} תווים",
|
"SwkbdMinRangeCharacters": "באורך {0}-{1} תווים",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "מקלדת וירטואלית",
|
"SoftwareKeyboard": "מקלדת וירטואלית",
|
||||||
"SoftwareKeyboardModeNumeric": "חייב להיות בין 0-9 או '.' בלבד",
|
"SoftwareKeyboardModeNumeric": "חייב להיות בין 0-9 או '.' בלבד",
|
||||||
"SoftwareKeyboardModeAlphabet": "מחויב להיות ללא אותיות CJK",
|
"SoftwareKeyboardModeAlphabet": "מחויב להיות ללא אותיות CJK",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Mai",
|
"Never": "Mai",
|
||||||
"SwkbdMinCharacters": "Non può avere meno di {0} caratteri",
|
"SwkbdMinCharacters": "Non può avere meno di {0} caratteri",
|
||||||
"SwkbdMinRangeCharacters": "Può avere da {0} a {1} caratteri",
|
"SwkbdMinRangeCharacters": "Può avere da {0} a {1} caratteri",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Tastiera software",
|
"SoftwareKeyboard": "Tastiera software",
|
||||||
"SoftwareKeyboardModeNumeric": "Deve essere solo 0-9 o '.'",
|
"SoftwareKeyboardModeNumeric": "Deve essere solo 0-9 o '.'",
|
||||||
"SoftwareKeyboardModeAlphabet": "Deve essere solo caratteri non CJK",
|
"SoftwareKeyboardModeAlphabet": "Deve essere solo caratteri non CJK",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "決して",
|
"Never": "決して",
|
||||||
"SwkbdMinCharacters": "最低 {0} 文字必要です",
|
"SwkbdMinCharacters": "最低 {0} 文字必要です",
|
||||||
"SwkbdMinRangeCharacters": "{0}-{1} 文字にしてください",
|
"SwkbdMinRangeCharacters": "{0}-{1} 文字にしてください",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "ソフトウェアキーボード",
|
"SoftwareKeyboard": "ソフトウェアキーボード",
|
||||||
"SoftwareKeyboardModeNumeric": "0-9 または '.' のみでなければなりません",
|
"SoftwareKeyboardModeNumeric": "0-9 または '.' のみでなければなりません",
|
||||||
"SoftwareKeyboardModeAlphabet": "CJK文字以外のみ",
|
"SoftwareKeyboardModeAlphabet": "CJK文字以外のみ",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "절대 안 함",
|
"Never": "절대 안 함",
|
||||||
"SwkbdMinCharacters": "{0}자 이상이어야 함",
|
"SwkbdMinCharacters": "{0}자 이상이어야 함",
|
||||||
"SwkbdMinRangeCharacters": "{0}-{1}자 길이여야 함",
|
"SwkbdMinRangeCharacters": "{0}-{1}자 길이여야 함",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "소프트웨어 키보드",
|
"SoftwareKeyboard": "소프트웨어 키보드",
|
||||||
"SoftwareKeyboardModeNumeric": "0-9 또는 '.'만 가능",
|
"SoftwareKeyboardModeNumeric": "0-9 또는 '.'만 가능",
|
||||||
"SoftwareKeyboardModeAlphabet": "CJK 문자가 아닌 문자만 가능",
|
"SoftwareKeyboardModeAlphabet": "CJK 문자가 아닌 문자만 가능",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Nigdy",
|
"Never": "Nigdy",
|
||||||
"SwkbdMinCharacters": "Musi mieć co najmniej {0} znaków",
|
"SwkbdMinCharacters": "Musi mieć co najmniej {0} znaków",
|
||||||
"SwkbdMinRangeCharacters": "Musi mieć długość od {0}-{1} znaków",
|
"SwkbdMinRangeCharacters": "Musi mieć długość od {0}-{1} znaków",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Klawiatura Oprogramowania",
|
"SoftwareKeyboard": "Klawiatura Oprogramowania",
|
||||||
"SoftwareKeyboardModeNumeric": "Może składać się jedynie z 0-9 lub '.'",
|
"SoftwareKeyboardModeNumeric": "Może składać się jedynie z 0-9 lub '.'",
|
||||||
"SoftwareKeyboardModeAlphabet": "Nie może zawierać znaków CJK",
|
"SoftwareKeyboardModeAlphabet": "Nie może zawierać znaków CJK",
|
||||||
|
|
|
@ -701,6 +701,9 @@
|
||||||
"Never": "Nunca",
|
"Never": "Nunca",
|
||||||
"SwkbdMinCharacters": "Deve ter pelo menos {0} caracteres",
|
"SwkbdMinCharacters": "Deve ter pelo menos {0} caracteres",
|
||||||
"SwkbdMinRangeCharacters": "Deve ter entre {0}-{1} caracteres",
|
"SwkbdMinRangeCharacters": "Deve ter entre {0}-{1} caracteres",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Teclado por Software",
|
"SoftwareKeyboard": "Teclado por Software",
|
||||||
"SoftwareKeyboardModeNumeric": "Deve ser somente 0-9 ou '.'",
|
"SoftwareKeyboardModeNumeric": "Deve ser somente 0-9 ou '.'",
|
||||||
"SoftwareKeyboardModeAlphabet": "Apenas devem ser caracteres não CJK.",
|
"SoftwareKeyboardModeAlphabet": "Apenas devem ser caracteres não CJK.",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Никогда",
|
"Never": "Никогда",
|
||||||
"SwkbdMinCharacters": "Должно быть не менее {0} символов.",
|
"SwkbdMinCharacters": "Должно быть не менее {0} символов.",
|
||||||
"SwkbdMinRangeCharacters": "Должно быть {0}-{1} символов",
|
"SwkbdMinRangeCharacters": "Должно быть {0}-{1} символов",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Программная клавиатура",
|
"SoftwareKeyboard": "Программная клавиатура",
|
||||||
"SoftwareKeyboardModeNumeric": "Должно быть в диапазоне 0-9 или '.'",
|
"SoftwareKeyboardModeNumeric": "Должно быть в диапазоне 0-9 или '.'",
|
||||||
"SoftwareKeyboardModeAlphabet": "Не должно быть CJK-символов",
|
"SoftwareKeyboardModeAlphabet": "Не должно быть CJK-символов",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "ไม่ต้อง",
|
"Never": "ไม่ต้อง",
|
||||||
"SwkbdMinCharacters": "ต้องมีความยาวของตัวอักษรอย่างน้อย {0} ตัว",
|
"SwkbdMinCharacters": "ต้องมีความยาวของตัวอักษรอย่างน้อย {0} ตัว",
|
||||||
"SwkbdMinRangeCharacters": "ต้องมีความยาวของตัวอักษร {0}-{1} ตัว",
|
"SwkbdMinRangeCharacters": "ต้องมีความยาวของตัวอักษร {0}-{1} ตัว",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "ซอฟต์แวร์คีย์บอร์ด",
|
"SoftwareKeyboard": "ซอฟต์แวร์คีย์บอร์ด",
|
||||||
"SoftwareKeyboardModeNumeric": "ต้องเป็น 0-9 หรือ '.' เท่านั้น",
|
"SoftwareKeyboardModeNumeric": "ต้องเป็น 0-9 หรือ '.' เท่านั้น",
|
||||||
"SoftwareKeyboardModeAlphabet": "ต้องเป็นตัวอักษรที่ไม่ใช่ประเภท CJK เท่านั้น",
|
"SoftwareKeyboardModeAlphabet": "ต้องเป็นตัวอักษรที่ไม่ใช่ประเภท CJK เท่านั้น",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Hiçbir Zaman",
|
"Never": "Hiçbir Zaman",
|
||||||
"SwkbdMinCharacters": "En az {0} karakter uzunluğunda olmalı",
|
"SwkbdMinCharacters": "En az {0} karakter uzunluğunda olmalı",
|
||||||
"SwkbdMinRangeCharacters": "{0}-{1} karakter uzunluğunda olmalı",
|
"SwkbdMinRangeCharacters": "{0}-{1} karakter uzunluğunda olmalı",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Yazılım Klavyesi",
|
"SoftwareKeyboard": "Yazılım Klavyesi",
|
||||||
"SoftwareKeyboardModeNumeric": "Sadece 0-9 veya '.' olabilir",
|
"SoftwareKeyboardModeNumeric": "Sadece 0-9 veya '.' olabilir",
|
||||||
"SoftwareKeyboardModeAlphabet": "Sadece CJK-characters olmayan karakterler olabilir",
|
"SoftwareKeyboardModeAlphabet": "Sadece CJK-characters olmayan karakterler olabilir",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "Ніколи",
|
"Never": "Ніколи",
|
||||||
"SwkbdMinCharacters": "Мінімальна кількість символів: {0}",
|
"SwkbdMinCharacters": "Мінімальна кількість символів: {0}",
|
||||||
"SwkbdMinRangeCharacters": "Має бути {0}-{1} символів",
|
"SwkbdMinRangeCharacters": "Має бути {0}-{1} символів",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "Програмна клавіатура",
|
"SoftwareKeyboard": "Програмна клавіатура",
|
||||||
"SoftwareKeyboardModeNumeric": "Повинно бути лише 0-9 або “.”",
|
"SoftwareKeyboardModeNumeric": "Повинно бути лише 0-9 або “.”",
|
||||||
"SoftwareKeyboardModeAlphabet": "Повинно бути лише не CJK-символи",
|
"SoftwareKeyboardModeAlphabet": "Повинно бути лише не CJK-символи",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "从不",
|
"Never": "从不",
|
||||||
"SwkbdMinCharacters": "不少于 {0} 个字符",
|
"SwkbdMinCharacters": "不少于 {0} 个字符",
|
||||||
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字符",
|
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字符",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "软键盘",
|
"SoftwareKeyboard": "软键盘",
|
||||||
"SoftwareKeyboardModeNumeric": "只能输入 0-9 或 \".\"",
|
"SoftwareKeyboardModeNumeric": "只能输入 0-9 或 \".\"",
|
||||||
"SoftwareKeyboardModeAlphabet": "仅支持非中文字符",
|
"SoftwareKeyboardModeAlphabet": "仅支持非中文字符",
|
||||||
|
|
|
@ -702,6 +702,9 @@
|
||||||
"Never": "從不",
|
"Never": "從不",
|
||||||
"SwkbdMinCharacters": "長度必須至少為 {0} 個字元",
|
"SwkbdMinCharacters": "長度必須至少為 {0} 個字元",
|
||||||
"SwkbdMinRangeCharacters": "長度必須為 {0} 到 {1} 個字元",
|
"SwkbdMinRangeCharacters": "長度必須為 {0} 到 {1} 個字元",
|
||||||
|
"CabinetTitle": "Cabinet Dialog",
|
||||||
|
"CabinetDialog": "Enter your Amiibo's new name",
|
||||||
|
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||||
"SoftwareKeyboard": "軟體鍵盤",
|
"SoftwareKeyboard": "軟體鍵盤",
|
||||||
"SoftwareKeyboardModeNumeric": "必須是 0 到 9 或「.」",
|
"SoftwareKeyboardModeNumeric": "必須是 0 到 9 或「.」",
|
||||||
"SoftwareKeyboardModeAlphabet": "必須是「非中日韓字元」 (non CJK)",
|
"SoftwareKeyboardModeAlphabet": "必須是「非中日韓字元」 (non CJK)",
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
|
@ -155,6 +156,55 @@ namespace Ryujinx.Ava.UI.Applet
|
||||||
return error || okPressed;
|
return error || okPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DisplayCabinetDialog(out string userText)
|
||||||
|
{
|
||||||
|
ManualResetEvent dialogCloseEvent = new(false);
|
||||||
|
bool okPressed = false;
|
||||||
|
string inputText = "My Amiibo";
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||||
|
SoftwareKeyboardUIArgs args = new SoftwareKeyboardUIArgs();
|
||||||
|
args.KeyboardMode = KeyboardMode.Default;
|
||||||
|
args.InitialText = "Ryujinx";
|
||||||
|
args.StringLengthMin = 1;
|
||||||
|
args.StringLengthMax = 25;
|
||||||
|
(UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args);
|
||||||
|
if (result == UserResult.Ok)
|
||||||
|
{
|
||||||
|
inputText = userInput;
|
||||||
|
okPressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dialogCloseEvent.Set();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogCloseEvent.WaitOne();
|
||||||
|
_parent.ViewModel.AppHost.NpadManager.UnblockInputUpdates();
|
||||||
|
userText = inputText;
|
||||||
|
return okPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayCabinetMessageDialog()
|
||||||
|
{
|
||||||
|
ManualResetEvent dialogCloseEvent = new(false);
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
dialogCloseEvent.Set();
|
||||||
|
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.CabinetScanDialog],
|
||||||
|
string.Empty,
|
||||||
|
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||||
|
string.Empty,
|
||||||
|
LocaleManager.Instance[LocaleKeys.CabinetTitle]);
|
||||||
|
});
|
||||||
|
dialogCloseEvent.WaitOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
|
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
|
||||||
{
|
{
|
||||||
device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
|
device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
|
||||||
|
|
Loading…
Reference in a new issue