Changes

8,891 bytes added ,  05:45, 3 June 2019
Line 1: Line 1:  
The software keyboard (swkbd) expects to be passed three [[AM_services#IStorage|IStorage]]s. See also [[AM_services#Library_Applets]].
 
The software keyboard (swkbd) expects to be passed three [[AM_services#IStorage|IStorage]]s. See also [[AM_services#Library_Applets]].
   −
The below is for normal swkbd usage. There's also InlineKeyboard (added post-1.0.0), which doesn't run in the foreground and has completely different input/output [[AM_services#IStorage|IStorage]]s. It also doesn't seem to display on the screen (or is optional at least): the user-process can get the gfx data via [[Display_services]].
+
The below is for normal swkbd usage, see the [[#InlineKeyboard]] section for InlineKeyboard.
 +
 
 +
With version 0x6000B+ after pushing all other storage: when [[#CustomizedDictionarySet]] was setup where buffer addr/size is set and total_entries is non-zero, [[Applet_Manager_services#CreateHandleStorage]] will be used to create TransferMemory storage which is then pushed.
    
== Library Applet Versions ==
 
== Library Applet Versions ==
Line 23: Line 25:  
|-
 
|-
 
| [5.0.0+] || 0x50009
 
| [5.0.0+] || 0x50009
 +
|-
 +
| [6.0.0+] || 0x6000B
 +
|-
 +
| [8.0.0+] || 0x8000D
 
|}
 
|}
   Line 43: Line 49:  
| 0x1A || 1 || 0 || Enables dictionary usage when non-zero (including the system dictionary).
 
| 0x1A || 1 || 0 || Enables dictionary usage when non-zero (including the system dictionary).
 
|-
 
|-
| 0x1C || 4 || 0 || Key set disable bitmask
+
| 0x1C || 4 || 0 || [[#Key Set Disable Bitmask]]
 
|-
 
|-
 
| 0x20 || 4 || 1 || Initial cursor position (0 = start of string, 1 = end of string)
 
| 0x20 || 4 || 1 || Initial cursor position (0 = start of string, 1 = end of string)
Line 59: Line 65:  
| 0x3B4 || 4 || 0 || Password flag (0 = not password, 1 = password)
 
| 0x3B4 || 4 || 0 || Password flag (0 = not password, 1 = password)
 
|-
 
|-
| 0x3B8 || 4 || 1 ||
+
| 0x3B8 || 4 || 1 || textDrawType
 
|-
 
|-
 
| 0x3BC || 2 || 1 || Return button flag (0 = disable, non-zero = enable)
 
| 0x3BC || 2 || 1 || Return button flag (0 = disable, non-zero = enable)
Line 74: Line 80:  
|-
 
|-
 
| 0x3D0 || 1 || 0 || [[#Text check]] enable
 
| 0x3D0 || 1 || 0 || [[#Text check]] enable
 +
|}
 +
 +
Before version 0x6000B:
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 0x3D8 || 8 || 0 || [[#Text check]] callback function address. Not sure why this is included here
+
! Offset || Size || Typical Value || Notes
 
|-
 
|-
| 0x3E0 || 8 || -1 ||  
+
| 0x3D8 || 8 || 0 || [[#Text check]] callback function address. Removed with the struct used by 0x6000B+.
 
|-
 
|-
| 0x3E8 || 8 || -1 ||  
+
| 0x3E0 || 0x20 || -1 || When set and enabled via textDrawType, controls displayed text grouping (inserts spaces, without affecting output string). Used for DownloadCodes, otherwise this is -1 normally.
 +
|}
 +
 
 +
Version 0x6000B+:
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 0x3F0 || 8 || -1 ||  
+
! Offset || Size || Typical Value || Notes
 
|-
 
|-
| 0x3F8 || 8 || -1 ||  
+
| 0x3D4 || 0x20 || -1 || When set and enabled via textDrawType, controls displayed text grouping (inserts spaces, without affecting output string). Used for DownloadCodes, otherwise this is -1 normally.
 +
|-
 +
| 0x3F4 || 0xC0 || 0 || [[#CustomizedDictionarySet]] array data.
 +
|-
 +
| 0x4B4 || 0x1 || 0 || Total array entries for [[#CustomizedDictionarySet]].
 +
|-
 +
| 0x4B5 || 0x1 || 0 || [8.0.0+] Cancel Button Flag (0 = do not disable cancel, 1 = disable cancel)
 +
|-
 +
| 0x4B6 || 0xD || 0 || Padding
 +
|-
 +
| 0x4C3 || 0x1 || 0 || [8.0.0+] Trigger
 +
|-
 +
| 0x4C4 || 0x4 || 0 || Padding
 
|}
 
|}
   −
This struct is 0x3E0-bytes with version 0x5. Starting with version 0x30007 this struct is 0x400-bytes.
+
Struct sizes:
 +
* Initial version: 0x3E0-bytes.
 +
* Version 0x30007+: 0x400-bytes.
 +
* Version 0x6000B+: 0x4C8-bytes.
   −
The 0x20-bytes at offset 0x3E0 is -1 normally, except for DownloadCodes. This is presumably an extension to [[#Key Set Disable Bitmask]]?(The field at 0x1C is still set to 0x80 here)
+
Each entry in the user dictionary is 100 bytes long.
 
  −
If the length limit (stringLenMax) is <= 32, the text entry box will be a line and show the header/sub text. Otherwise, it will use a text-box and the header/sub text will not be shown. When the input is too long, swkbd will stop accepting more input until text is deleted via the B button (Backspace).
     −
Each entry in the user dictionary is 100 bytes long.
+
stringLenMax: When the input is too long, swkbd will stop accepting more input until text is deleted via the B button (Backspace).
   −
== Type ==
+
=== Type ===
 
* 0: Normal keyboard.
 
* 0: Normal keyboard.
 
* 1: Number pad. The buttons at the bottom left/right are only available when the characters at offset 0x16/0x18 are set.
 
* 1: Number pad. The buttons at the bottom left/right are only available when the characters at offset 0x16/0x18 are set.
 
* 2: QWERTY (and variants) keyboard only.
 
* 2: QWERTY (and variants) keyboard only.
 +
 +
=== textDrawType ===
 +
If the length limit (stringLenMax) is 1..32, the type specified by textDrawType will be used. Otherwise, type1 will be used.
 +
 +
* 0: The text will be displayed on a line. Also enables displaying the Header and Sub text.
 +
* 1: The text will be displayed in a box.
 +
* 2: Used for DownloadCodes on 5.0.0+. Enables using the data starting at offset 0x3E0.
    
=== Key Set Disable Bitmask ===
 
=== Key Set Disable Bitmask ===
 
+
Various bits in this u32 field disable certain keys on the keyboard.
Various bits in this field disable certain keys on the keyboard. This list is incomplete.
      
<pre>
 
<pre>
Line 107: Line 140:  
0x04: disable '@'
 
0x04: disable '@'
 
0x08: disable '%'
 
0x08: disable '%'
0x10: disable '\' and '/'
+
0x10: disable '/'
 +
0x20: disable '\'
 
0x40: disable numbers
 
0x40: disable numbers
0x80: used for download codes
+
0x80: Used for DownloadCodes.
 +
0x100: Used for UserNames. Disables '@', '%', and '\'.
 
</pre>
 
</pre>
   Line 174: Line 209:  
|-
 
|-
 
|}
 
|}
 +
 +
== InlineKeyboard ==
 +
This doesn't run in the foreground and has completely different input/output [[AM_services#IStorage|IStorage]]s. This is essentially an asynchronous version of the regular swkbd. Whether it displays on the screen is controlled by the user-process. The user-process can also get the gfx data via [[Display_services]]. InlineKeyboard was added with 2.0.0, however it wasn't added to sdk-nso until the version corresponding to sysver 3.x (even though 2.0.0 system titles use it).
 +
 +
=== InitializeArg ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Notes
 +
|-
 +
| 0x0 || 0x4 || Unknown, normally 0.
 +
|-
 +
| 0x4 || 0x1 || Controls the LibraryAppletMode when launching the applet. Non-zero indicates LibraryAppletMode=0x1, otherwise LibraryAppletMode=0x3.
 +
|-
 +
| 0x5 || 0x1 || Set to 0x1 with [5.0.0+] in a separate init func by official sw, originally set to value 0.
 +
|-
 +
| 0x6 || 0x2 || Padding
 +
|}
 +
 +
=== AppearArg ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Notes
 +
|-
 +
| 0x0 || 0x4 || Initialized to value 0x2.
 +
|-
 +
| 0x4 || 0x12 || UTF-16 string okButtonText
 +
|-
 +
| 0x16 || 2 || UTF-16 "left optional symbol key"
 +
|-
 +
| 0x18 || 2 || UTF-16 "right optional symbol key"
 +
|-
 +
| 0x1A || 0x1 || Enables dictionary usage when non-zero (including the system dictionary).
 +
|-
 +
| 0x1B || 0x1 ||
 +
|-
 +
| 0x1C || 0x4 || [[#Key Set Disable Bitmask]]
 +
|-
 +
| 0x20 || 0x4 || s32, Unknown. Initialized to value -1.
 +
|-
 +
| 0x24 || 0x4 || s32, Unknown. Initialized to value -1.
 +
|-
 +
| 0x28 || 0x1 || Return button flag (0 = disable, non-zero = enable)
 +
|-
 +
| 0x29 || 0x2 ||
 +
|-
 +
| 0x2B || 0x1 ||
 +
|-
 +
| 0x2C || 0x4 || [4.0.0+] [[#CalcArg]] flags bitmask 0x1000. In this field, bitmask 0x10000000 is used for DirectionalButtonAssignEnabled.
 +
|-
 +
| 0x30 || 0x1 || Initialized to value 1.
 +
|-
 +
| 0x31 || 0x17 ||
 +
|}
 +
 +
The above struct is cleared to 0 during initialization, besides the fields specified otherwise.
 +
 +
[6.0.0+] Flags bitmask 0x10000 is set when [[#CalcArg]] trigger is set.
 +
 +
=== CalcArg ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Flags bitmask || Notes
 +
|-
 +
| 0x0 || 0x4 || || Set to 0x30000.
 +
|-
 +
| 0x4 || 0x2 || || Size of this struct.
 +
|-
 +
| 0x6 || 0x1 || || Unknown, set to value 0x1.
 +
|-
 +
| 0x7 || 0x1 || || Unknown, set to value 0x1.
 +
|-
 +
| 0x8 || 0x8 || || Flags
 +
|-
 +
| 0x10 || 0x8 || 0x1 || [[#InitializeArg]]
 +
|-
 +
| 0x18 || 0x4 || 0x2 || float volume
 +
|-
 +
| 0x1C || 0x4 || 0x10 || s32 cursorPos
 +
|-
 +
| 0x20 || 0x48 || || [[#AppearArg]]
 +
|-
 +
| 0x68 || 0x3F4 || 0x8 || InputText UTF-16 string
 +
|-
 +
| 0x45C || 0x1 || 0x20 || utf8Mode
 +
|-
 +
| 0x45D || 0x1 || || Unknown
 +
|-
 +
| 0x45E || 0x1 || 0x8000 || [5.0.0+] enableBackspace
 +
|-
 +
| 0x45F || 0x3 || || Unknown
 +
|-
 +
| 0x462 || 0x1 || 0x200 || keytopAsFloating
 +
|-
 +
| 0x463 || 0x1 || 0x100 || footerScalable
 +
|-
 +
| 0x464 || 0x1 || 0x100 || alphaEnabledInInputMode
 +
|-
 +
| 0x465 || 0x1 || 0x100 || inputModeFadeType
 +
|-
 +
| 0x466 || 0x1 || 0x200 || disableTouch
 +
|-
 +
| 0x467 || 0x1 || 0x800 || disableUSBKeyboard
 +
|-
 +
| 0x468 || 0x5 || || Unknown
 +
|-
 +
| 0x46D || 0x2 || ||
 +
|-
 +
| 0x46F || 0x1 || ||
 +
|-
 +
| 0x470 || 0x4 || 0x200 || float keytopScale0
 +
|-
 +
| 0x474 || 0x4 || 0x200 || float keytopScale1
 +
|-
 +
| 0x478 || 0x4 || 0x200 || float keytopTranslate0
 +
|-
 +
| 0x47C || 0x4 || 0x200 || float keytopTranslate1
 +
|-
 +
| 0x480 || 0x4 || 0x100 || float keytopBgAlpha
 +
|-
 +
| 0x484 || 0x4 || 0x100 || float footerBgAlpha
 +
|-
 +
| 0x488 || 0x4 || 0x200 || float balloonScale
 +
|-
 +
| 0x48C || 0x4 || || float, unknown
 +
|-
 +
| 0x490 || 0xC || ||
 +
|-
 +
| 0x49C || 0x1 || Enable=0x2000, disable=0x4000. || [5.0.0+] SeGroup (sound effect)
 +
|-
 +
| 0x49D || 0x1 || || [6.0.0+] u8 triggerFlag, for [[#AppearArg]]. Enables using the trigger field when set, this is only set when trigger is non-zero.
 +
|-
 +
| 0x49E || 0x2 || || [6.0.0+] u8 trigger, for [[#AppearArg]]. Official sw currently only uses value 0.
 +
|-
 +
| 0x49F || 0x1 || || Padding
 +
|-
 +
|}
 +
 +
This is 0x4A0-bytes.
 +
 +
All floats except for keytopTranslate0/keytopTranslate1 are initialized to value 1.0f.
 +
 +
The applet-specific IStorage for data input is the [[#InitializeArg]] within this struct.
 +
 +
=== Runtime ===
 +
Once the applet is running, official sw can call a func which does the following:
 +
* Checks whether the applet exited via an event, then handles exit if so and returns.
 +
* Otherwise:
 +
** If the Flags field in the [[#CalcArg]] state is non-zero, sends a Calc [[#Request]] then clears the Flags field.
 +
** Enters a loop which pops each applet Interactive output IStorage, reads 2 u32s from the [[#Reply]] storage and processes the reply.
 +
** The u32 from offset 0x0 from the last processed storage is then returned as the retval.
 +
 +
=== Request ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! RequestCommand || Data Size || Name || Notes
 +
|-
 +
| 0x4 || 0x0 || Finalize ||
 +
|-
 +
| 0x6 || Varies || SetUserWordInfo ||
 +
|-
 +
| 0x7 || 0x70 || SetCustomizeDic ||
 +
|-
 +
| 0xA || 0x4A0 || Calc || Data is [[#CalcArg]].
 +
|-
 +
| 0xB || 0xD0 || SetCustomizedDictionaries || Data is [[#CustomizedDictionarySet]] with an additional 2-bytes of padding.
 +
|-
 +
| 0xC || 0x0 || UnsetCustomizedDictionaries ||
 +
|-
 +
| 0xD || 0x1 || [8.0.0+] || Takes an input u8 bool which controls whether ChangedString*V2 or ChangedString* replies should be used.
 +
|-
 +
| 0xE || 0x1 || [8.0.0+] || Takes an input u8 bool which controls whether MovedCursor*V2 or MovedCursor* replies should be used.
 +
|}
 +
 +
Requests are sent via an applet Interactive input IStorage: the u32 at offset 0x0 is the RequestCommand, and the rest of the storage is the request-specific data. While swkbd supports other requests, official sw only uses requests 0x4, 0x7, and 0xA.
 +
 +
=== Reply ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! ReplyType || Data Size || Name || Notes
 +
|-
 +
| 0x0 || 0x1 || FinishedInitialize || Reply data is ignored by the user-process.
 +
|-
 +
| 0x1 / default case || 0x0 || || Official sw has no handling for this besides just closing the storage.
 +
|-
 +
| 0x2 || 0x3FC || ChangedString ||
 +
|-
 +
| 0x3 || 0x3F4 || MovedCursor ||
 +
|-
 +
| 0x4 || 0x3F4 || MovedTab ||
 +
|-
 +
| 0x5 || 0x3F0 || DecidedEnter ||
 +
|-
 +
| 0x6 || 0x0 || DecidedCancel ||
 +
|-
 +
| 0x7 || 0x7E4 || ChangedStringUtf8 ||
 +
|-
 +
| 0x8 || 0x7DC || MovedCursorUtf8 ||
 +
|-
 +
| 0x9 || 0x7D8 || DecidedEnterUtf8 ||
 +
|-
 +
| 0xA || 0x0 || UnsetCustomizeDic || Official sw clears a flag related to CustomizeDic, then runs the same handling code as 0x1/default.
 +
|-
 +
| 0xB || 0x0 || ReleasedUserWordInfo ||
 +
|-
 +
| 0xC || 0x0 || UnsetCustomizedDictionaries || [6.0.0+] Official sw handles this the same as UnsetCustomizeDic.
 +
|-
 +
| 0xD || 0x3FC + 0x1 || ChangedStringV2 || [8.0.0+]
 +
|-
 +
| 0xE || 0x3F4 + 0x1 || MovedCursorV2 || [8.0.0+]
 +
|-
 +
| 0xF || 0x7E4 + 0x1 || ChangedStringUtf8V2 || [8.0.0+]
 +
|-
 +
| 0x10 || 0x7DC + 0x1 || MovedCursorUtf8V2 || [8.0.0+]
 +
|-
 +
|}
 +
 +
See [[#Runtime]]. In the storage, the first u32 is the State, while the second u32 is the ReplyType. The rest is the reply-specific data.
 +
 +
The replies with name "*Utf8" contain an UTF-8 string in the reply data, while the other replies contain an UTF-16 string. These are identical besides the string encoding.
 +
 +
Reply data format:
 +
* ChangedString*: +0 = string. Last 0x10-bytes: 4 u32s, where the first one is the length of the string in characters, without NUL-terminator. The last u32 is cursorPos. The other 2 fields are s32s.
 +
* MovedCursor*: +0 = string. Last 0x8-bytes: 2 u32s, where the first one is the stringLen, and the second one is cursorPos.
 +
* DecidedEnter*: +0 = string. The last u32 is the stringLen.
 +
* *V2: See above. Last byte: u8 bool, passed to the callback as <code>flag==0</code>.
 +
 +
== CustomizedDictionarySet ==
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x8 || 0x1000-byte aligned buffer address.
 +
|-
 +
| 0x8 || 0x4 || 0x1000-byte aligned buffer size.
 +
|-
 +
| 0xC || 0x18*4(0xC0) || Array of 0x18 entries, where each entry is 0x8-bytes.
 +
|-
 +
| 0xCC || 0x2 || u16 total_entries
 +
|}
 +
 +
This was added with [6.0.0+]. This struct is 0xCE-bytes.
    
[[Category:Library Applets]]
 
[[Category:Library Applets]]