am: Fully reverse swkbd configuration structure
This commit is contained in:
parent
bb7600e215
commit
4e38cadcad
3 changed files with 236 additions and 35 deletions
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -22,7 +23,8 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
|
|
||||||
private SoftwareKeyboardConfig _keyboardConfig;
|
private SoftwareKeyboardConfig _keyboardConfig;
|
||||||
|
|
||||||
private string _textValue = DEFAULT_TEXT;
|
private string _textValue = DEFAULT_TEXT;
|
||||||
|
private Encoding _encoding = Encoding.Unicode;
|
||||||
|
|
||||||
public event EventHandler AppletStateChanged;
|
public event EventHandler AppletStateChanged;
|
||||||
|
|
||||||
|
@ -41,6 +43,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
var transferMemory = _normalSession.Pop();
|
var transferMemory = _normalSession.Pop();
|
||||||
|
|
||||||
_keyboardConfig = ReadStruct<SoftwareKeyboardConfig>(keyboardConfig);
|
_keyboardConfig = ReadStruct<SoftwareKeyboardConfig>(keyboardConfig);
|
||||||
|
_encoding = _keyboardConfig.UseUtf8 ? Encoding.UTF8 : Encoding.Unicode;
|
||||||
|
|
||||||
_state = SoftwareKeyboardState.Ready;
|
_state = SoftwareKeyboardState.Ready;
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
{
|
{
|
||||||
// If the keyboard type is numbers only, we swap to a default
|
// If the keyboard type is numbers only, we swap to a default
|
||||||
// text that only contains numbers.
|
// text that only contains numbers.
|
||||||
if (_keyboardConfig.Type == SoftwareKeyboardType.NumbersOnly)
|
if (_keyboardConfig.Mode == KeyboardMode.NumbersOnly)
|
||||||
{
|
{
|
||||||
_textValue = DEFAULT_NUMB;
|
_textValue = DEFAULT_NUMB;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +73,15 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
_keyboardConfig.StringLengthMax = 100;
|
_keyboardConfig.StringLengthMax = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the game requests a string with a minimum length less
|
||||||
|
// than our default text, repeat our default text until we meet
|
||||||
|
// the minimum length requirement.
|
||||||
|
// This should always be done before the text truncation step.
|
||||||
|
while (_textValue.Length < _keyboardConfig.StringLengthMin)
|
||||||
|
{
|
||||||
|
_textValue = String.Join(" ", _textValue, _textValue);
|
||||||
|
}
|
||||||
|
|
||||||
// If our default text is longer than the allowed length,
|
// If our default text is longer than the allowed length,
|
||||||
// we truncate it.
|
// we truncate it.
|
||||||
if (_textValue.Length > _keyboardConfig.StringLengthMax)
|
if (_textValue.Length > _keyboardConfig.StringLengthMax)
|
||||||
|
@ -77,6 +89,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
_textValue = _textValue.Substring(0, (int)_keyboardConfig.StringLengthMax);
|
_textValue = _textValue.Substring(0, (int)_keyboardConfig.StringLengthMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Does the application want to validate the text itself?
|
||||||
if (!_keyboardConfig.CheckText)
|
if (!_keyboardConfig.CheckText)
|
||||||
{
|
{
|
||||||
// If the application doesn't need to validate the response,
|
// If the application doesn't need to validate the response,
|
||||||
|
@ -136,12 +149,12 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
|
|
||||||
private byte[] BuildResponse(string text, bool interactive)
|
private byte[] BuildResponse(string text, bool interactive)
|
||||||
{
|
{
|
||||||
int bufferSize = !interactive ? STANDARD_BUFFER_SIZE : INTERACTIVE_BUFFER_SIZE;
|
int bufferSize = interactive ? INTERACTIVE_BUFFER_SIZE : STANDARD_BUFFER_SIZE;
|
||||||
|
|
||||||
using (MemoryStream stream = new MemoryStream(new byte[bufferSize]))
|
using (MemoryStream stream = new MemoryStream(new byte[bufferSize]))
|
||||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||||
{
|
{
|
||||||
byte[] output = Encoding.Unicode.GetBytes(text);
|
byte[] output = _encoding.GetBytes(text);
|
||||||
|
|
||||||
if (!interactive)
|
if (!interactive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,32 +2,240 @@
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
||||||
{
|
{
|
||||||
// TODO(jduncanator): Define all fields
|
/// <summary>
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
///
|
||||||
|
/// </summary>
|
||||||
|
internal enum KeyboardMode : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Normal keyboard.
|
||||||
|
/// </summary>
|
||||||
|
Default,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number pad. The buttons at the bottom left/right are only available when they're set in the config by leftButtonText / rightButtonText.
|
||||||
|
/// </summary>
|
||||||
|
NumbersOnly,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QWERTY (and variants) keyboard only.
|
||||||
|
/// </summary>
|
||||||
|
LettersOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
internal enum InvalidCharFlags : uint
|
||||||
|
{
|
||||||
|
None = 0 << 1,
|
||||||
|
|
||||||
|
Space = 1 << 1,
|
||||||
|
|
||||||
|
AtSymbol = 1 << 2,
|
||||||
|
|
||||||
|
Percent = 1 << 3,
|
||||||
|
|
||||||
|
ForwardSlash = 1 << 4,
|
||||||
|
|
||||||
|
BackSlash = 1 << 5,
|
||||||
|
|
||||||
|
Numbers = 1 << 6,
|
||||||
|
|
||||||
|
DownloadCode = 1 << 7,
|
||||||
|
|
||||||
|
Username = 1 << 8
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
internal enum PasswordMode : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
Disabled,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
internal enum InputFormMode : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
SingleLine,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
MultiLine
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
internal enum InitialCursorPosition : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
Start,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
End
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
struct SoftwareKeyboardConfig
|
struct SoftwareKeyboardConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
const int SubmitTextLength = 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
const int HeaderTextLength = 64;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
const int SubtitleTextLength = 128;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
const int GuideTextLength = 256;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of keyboard.
|
/// Type of keyboard.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FieldOffset(0x0)]
|
public KeyboardMode Mode;
|
||||||
public SoftwareKeyboardType Type;
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SubmitTextLength + 1)]
|
||||||
|
public string SubmitText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public char LeftOptionalSymbolKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public char RightOptionalSymbolKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
public bool PredictionEnabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public InvalidCharFlags InvalidCharFlag;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public InitialCursorPosition InitialCursorPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HeaderTextLength + 1)]
|
||||||
|
public string HeaderText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SubtitleTextLength + 1)]
|
||||||
|
public string SubtitleText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = GuideTextLength + 1)]
|
||||||
|
public string GuideText;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When non-zero, specifies the max string length. When the input is too long, swkbd will stop accepting more input until text is deleted via the B button (Backspace).
|
/// When non-zero, specifies the max string length. When the input is too long, swkbd will stop accepting more input until text is deleted via the B button (Backspace).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FieldOffset(0x3AC)]
|
public int StringLengthMax;
|
||||||
public uint StringLengthMax;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When non-zero, specifies the max string length. When the input is too long, swkbd will display an icon and disable the ok-button.
|
/// When non-zero, specifies the minimum string length.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FieldOffset(0x3B0)]
|
public int StringLengthMin;
|
||||||
public uint StringLengthMaxExtended;
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public PasswordMode PasswordMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public InputFormMode InputFormMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
public bool UseNewLine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When set, the software keyboard will return a string UTF-8 encoded, rather than UTF-16.
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
public bool UseUtf8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
public bool UseBlurBackground;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int InitialStringOffset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int InitialStringLength;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int CustomDictionaryOffset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int CustomDictionaryCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When set, the application will validate the entered text whilst the swkbd is still on screen.
|
/// When set, the application will validate the entered text whilst the swkbd is still on screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FieldOffset(0x3D0), MarshalAs(UnmanagedType.I1)]
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
public bool CheckText;
|
public bool CheckText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|
||||||
{
|
|
||||||
internal enum SoftwareKeyboardType : uint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Normal keyboard.
|
|
||||||
/// </summary>
|
|
||||||
Default = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number pad. The buttons at the bottom left/right are only available when they're set in the config by leftButtonText / rightButtonText.
|
|
||||||
/// </summary>
|
|
||||||
NumbersOnly = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// QWERTY (and variants) keyboard only.
|
|
||||||
/// </summary>
|
|
||||||
LettersOnly = 2
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue