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]] |