Ring-Con: Difference between revisions

No edit summary
 
(5 intermediate revisions by one other user not shown)
Line 1: Line 1:
This page documents how the Ring Fit Adventure game uses [[HID_services#hidbus|hidbus]] for using the Ring-Con ExternalDevice, which attaches to Joy-Cons.
This page documents how the Ring Fit Adventure game uses [[HID_services#hidbus|hidbus]] for using the Ring-Con [[HID_services#ExternalDevices|ExternalDevice]], which attaches to Joy-Cons.


The [[HID_services#BusType|BusType]] used with GetBusHandle is value 0 or 1.
After EnableExternalDevice is used successfully during initialization, EnableJoyPollingReceiveMode(flag=true) is used with command [[#0x00020101]]. For cleanup, DisableJoyPollingReceiveMode is used then on success EnableExternalDevice(flag=false) is used.
 
The ExternalDeviceId is 0x20. After EnableExternalDevice is used successfully during initialization, EnableJoyPollingReceiveMode(flag=true) is used with command [[#0x00020101]]. For cleanup, DisableJoyPollingReceiveMode is used then on success EnableExternalDevice(flag=false) is used.


Commands (input data for EnableJoyPollingReceiveMode / SendAndReceive) start with the u32 cmd. Data in the replies are at least 0x4-bytes, with fields being 4-byte aligned. Reply+0 is the u8 status. When the output size doesn't match the expected size, or status is non-zero, error 0xEDA is returned. When status is non-zero, a func is called with the status value which updates global state.
Commands (input data for EnableJoyPollingReceiveMode / SendAndReceive) start with the u32 cmd. Data in the replies are at least 0x4-bytes, with fields being 4-byte aligned. Reply+0 is the u8 status. When the output size doesn't match the expected size, or status is non-zero, error 0xEDA is returned. When status is non-zero, a func is called with the status value which updates global state.


The status field is not listed below since all replies have it.
The status field is not listed below since all replies have it.
Note that the app saves various PlayReports, this includes various Ring-Con data (which includes field-name strings).


= CRC =
= CRC =
Line 15: Line 15:


= Commands =
= Commands =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
Line 66: Line 65:
The two u8s at reply+0x4 are copied to an output struct, with the order swapped in the output struct. This is also used directly by various funcs, without the struct.
The two u8s at reply+0x4 are copied to an output struct, with the order swapped in the output struct. This is also used directly by various funcs, without the struct.


This is probably some version field or similar? Funcs using this do: <code>if (u8 reply_x5 >= 0x20) {} else {}</code>
Reply u8 +0x4 is "fw_sub_ver", +0x5 is "fw_main_ver".
 
This gets the firmware version. Funcs using this do: <code>if (fw_main_ver >= 0x20) {} else {}</code>


== 0x00020100 ==
== 0x00020100 ==
This gets the ID. The first 0x6-bytes from the below output is "id_l", the remaining 0x6-bytes are "id_h". During PlayReport saving the cached ID is copied to u64s, which are then used with the PlayReport.
Reply:
Reply:


Line 75: Line 78:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x4 || 0x8 || u64 copied to an output struct.
| 0x4 || 0xC || This is copied to an output buffer.
|-
| 0xC || 0x4 || u32 copied to an output struct.
|}
|}


Line 89: Line 90:


== 0x00020105 ==
== 0x00020105 ==
Reply+0x4 is the output u8.
Reply+0x4 is the output u8, which copied to an output u32.


== 0x00020204 ==
== 0x00020204 ==
Line 107: Line 108:


== 0x00020504 ==
== 0x00020504 ==
Reply+0x4 is a s16. After successfully using this cmd, this calls the func for [[#0x00020A04]]. When that's successful, this does the following with the output from that func and the earlier reply data: <code>s16 tmp = s16_struct_x2 - s16_struct_x0; if (tmp < 0) tmp++; *16bit_outparam = replydata + (tmp>>1);</code> Then this returns 0, regardless of whether [[#0x00020A04]] was successful.
Reply+0x4 is a s16. After successfully using this cmd, this calls the func for [[#0x00020A04]]. When that's successful, this does the following with the output from that func and the earlier reply data: <code>s16 tmp = s16 manu_hk_max - s16 manu_os_max; if (tmp < 0) tmp++; *16bit_outparam = replydata + (tmp>>1);</code> Then this returns 0, regardless of whether [[#0x00020A04]] was successful.


== 0x00020A04 ==
== 0x00020A04 ==
The app uses cmd [[#0x00020000]] first. When u8 reply_x5 from that cmd is >=0x20, it proceeds to use cmd 0x00020A04 then returns. Otherwise, the following cmds are used with the output being copied to the output struct, then returns: [[#0x00020104]] (output_struct+0x0), [[#0x00020204]] (output_struct+0x2), [[#0x00020404]] (output_struct+0x6), [[#0x00020304]] (output_struct+0x4).
The app uses cmd [[#0x00020000]] first. When fw_main_ver from that cmd is >=0x20, it proceeds to use cmd 0x00020A04 then returns. Otherwise, the following cmds are used with the output being copied to the output struct, then returns: [[#0x00020104]] (output_struct+0x0), [[#0x00020204]] (output_struct+0x2), [[#0x00020404]] (output_struct+0x6), [[#0x00020304]] (output_struct+0x4).
 
The func for this is only called by the func implementing [[#0x00020504]].


Reply:
Reply:
Line 120: Line 119:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x4 || 0x2 || 16bit value copied to output_struct+0x0.
| 0x4 || 0x2 || "manu_os_max". s16 value copied to output_struct+0x0.
|-
|-
| 0x8 || 0x2 || 16bit value copied to output_struct+0x2.
| 0x8 || 0x2 || "manu_hk_max". s16 value copied to output_struct+0x2.
|-
|-
| 0xC || 0x2 || 16bit value copied to output_struct+0x4.
| 0xC || 0x2 || "manu_zero_min". s16 value copied to output_struct+0x4.
|-
|-
| 0x10 || 0x2 || 16bit value copied to output_struct+0x6.
| 0x10 || 0x2 || "manu_zero_max". s16 value copied to output_struct+0x6.
|}
|}


Line 142: Line 141:
| 0x4 || 0x2 || Data, copied to an output struct as an 16bit value.
| 0x4 || 0x2 || Data, copied to an output struct as an 16bit value.
|-
|-
| 0x6 || 0x1 || [[#CRC]] over the previous 0x3-bytes.
| 0x6 || 0x1 || [[#CRC]] over the previous 0x2-bytes.
|}
|}


Line 152: Line 151:


== 0x00021A04 ==
== 0x00021A04 ==
The app uses cmd [[#0x00020000]] first. When u8 reply_x5 from that cmd is >=0x20, it proceeds to use cmd 0x00021A04. Otherwise, the following cmds are used, with the output being written to the output_struct: [[#0x00021104]] (output_struct+0x0), [[#0x00021204]] (output_struct+0x2), [[#0x00021304]] (output_struct+0x4).
The app uses cmd [[#0x00020000]] first. When fw_main_ver from that cmd is >=0x20, it proceeds to use cmd 0x00021A04. Otherwise, the following cmds are used, with the output being written to the output_struct: [[#0x00021104]] (output_struct+0x0), [[#0x00021204]] (output_struct+0x2), [[#0x00021304]] (output_struct+0x4).


Then, if any of the 16bit output fields in output_struct are set to 0xCAFE, a flag is set to 0x2 (same field used for invalid-CRC, which uses value 0x1 for that). Then this returns 0.
Then, if any of the 16bit output fields in output_struct are set to 0xCAFE, a flag is set to 0x2 (same field used for invalid-CRC, which uses value 0x1 for that). Then this returns 0. This field is "user_state".


This reads the user calibration.
This reads the user calibration. This is normally (?) not calibrated (fields are set to 0xCAFE).


Reply:
Reply:
Line 164: Line 163:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x4 || 0x2 || "os_max". s16 value copied to output_struct+0x0.
| 0x4 || 0x2 || "user_os_max"/"os_max". s16 value copied to output_struct+0x0.
|-
|-
| 0x6 || 0x1 || [[#CRC]] over the previous 0x2-bytes.
| 0x6 || 0x1 || [[#CRC]] over the previous 0x2-bytes.
Line 170: Line 169:
| 0x7 || 0x1 || Padding.
| 0x7 || 0x1 || Padding.
|-
|-
| 0x8 || 0x2 || "hk_max". s16 value copied to output_struct+0x2.
| 0x8 || 0x2 || "user_hk_max"/"hk_max". s16 value copied to output_struct+0x2.
|-
|-
| 0xA || 0x1 || [[#CRC]] over the previous 0x2-bytes.
| 0xA || 0x1 || [[#CRC]] over the previous 0x2-bytes.
Line 176: Line 175:
| 0xB || 0x1 || Padding.
| 0xB || 0x1 || Padding.
|-
|-
| 0xC || 0x2 || "zero". s16 value copied to output_struct+0x4.
| 0xC || 0x2 || "user_zero"/"zero". s16 value copied to output_struct+0x4.
|-
|-
| 0xE || 0x1 || [[#CRC]] over the previous 0x2-bytes.
| 0xE || 0x1 || [[#CRC]] over the previous 0x2-bytes.
Line 184: Line 183:


== 0x00023104 ==
== 0x00023104 ==
The code which calls the func implementing this clamps the output value to range 0-500, then copies it elsewhere. Hence, this is probably the rep-count for Multitask Mode?
The code which calls the func implementing this clamps the output value to range 0-500, then copies it elsewhere.
 
This gets the rep-count for Multitask-Mode.


Reply:
Reply:
Line 194: Line 195:
| 0x4 || 0x3 || Data, copied to an output struct as a s32.
| 0x4 || 0x3 || Data, copied to an output struct as a s32.
|-
|-
| 0x7 || 0x1 || [[#CRC]] over the previous 0x3-bytes.
| 0x7 || 0x1 || [[#CRC]] over the previous 0x3-bytes, followed a value-0 byte.
|}
|}


== 0x00023204 ==
== 0x00023204 ==
The func implementing this in the app is identical to [[#0x00023104]] except for the cmd u32.
The func implementing this in the app is identical to [[#0x00023104]] except for the cmd u32. The output field is "total_push_count". This is only updated in Multitask Mode.


The code calling this func copies the output into a global field, when it's valid.
The code calling this func copies the output into a global field, when it's valid.
Line 206: Line 207:


Unlike the other cmds, this checks for output_size==0x4, instead of {output buffer size} (it's unknown whether this is intended).
Unlike the other cmds, this checks for output_size==0x4, instead of {output buffer size} (it's unknown whether this is intended).
This resets the value returned by [[#0x00023104]] to 0.


== 0x04011104 ==
== 0x04011104 ==
Line 223: Line 226:


== 0x10011A04 ==
== 0x10011A04 ==
The app uses cmd [[#0x00020000]] first. When u8 reply_x5 from that cmd is >=0x20, it proceeds to use cmd 0x10011A04 then returns. Otherwise, the following cmds are used, with the same 4-byte input listed in the below table: [[#0x04011104]] (below cmd+0x4), [[#0x04011204]] (below cmd+0x8), [[#0x04011304]] (below cmd+0xC).
The app uses cmd [[#0x00020000]] first. When fw_main_ver from that cmd is >=0x20, it proceeds to use cmd 0x10011A04 then returns. Otherwise, the following cmds are used, with the same 4-byte input listed in the below table: [[#0x04011104]] (below cmd+0x4), [[#0x04011204]] (below cmd+0x8), [[#0x04011304]] (below cmd+0xC).


The app doesn't use reply data here besides the status, and the output_size is not checked.
The app doesn't use reply data here besides the status, and the output_size is not checked.
Line 232: Line 235:


Cmd:
Cmd:
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-