Mario Kart Live: Home Circuit: Difference between revisions
Cmdblkster (talk | contribs) m Added new information about the "product_code" parameter |
|||
Line 1: | Line 1: | ||
This page documents the Mario Kart Live: Home Circuit game. | This page documents the Mario Kart Live: Home Circuit game. | ||
Communication with the kart is done directly over local-WLAN via an access point that the game sets up using [[ | Communication with the kart is done directly over local-WLAN via an access point that the game sets up using [[LDN services|lp2p:app]], making it the first title on retail to use lp2p. The underlying device management uses [[RCD]]. The RCD implementation is in the main-codebin itself, without symbols - however there are strings for this. | ||
This is also the first known title on retail which uses stack cookies. This is used by main-codebin, the ssp functionality in sdknso is still not used other than being called from an initialization func. This is implemented in the main-codebin as follows: | This is also the first known title on retail which uses stack cookies. This is used by main-codebin, the ssp functionality in sdknso is still not used other than being called from an initialization func. This is implemented in the main-codebin as follows: | ||
* The global u64 __stack_chk_guard is loaded then saved immediately before {first saved register} on stack, during func entry. During func exit, the global u64 is compared with the cookie on stack, it will call __stack_chk_fail on mismatch. __stack_chk_fail just executes an undefined instruction to trigger a crash. | * The global u64 __stack_chk_guard is loaded then saved immediately before {first saved register} on stack, during func entry. During func exit, the global u64 is compared with the cookie on stack, it will call __stack_chk_fail on mismatch. __stack_chk_fail just executes an undefined instruction to trigger a crash. | ||
* There is no initialization func for __stack_chk_guard, it's just a hard-coded constant: 0xDEADBEEFDEADBEEF. Since it's constant, this renders the stack cookie useless. | * There is no initialization func for __stack_chk_guard, it's just a hard-coded constant: 0xDEADBEEFDEADBEEF. Since it's constant, this renders the stack cookie useless. | ||
RomFs contains only two files: | RomFs contains only two files: | ||
* "data.zip" | * "data.zip" | ||
* "update.pua": This is the firmware update data for the Kart. This is a tar archive. The extracted archive contains "update.pui" and "pui.hash". The latter is a binary 0x100-byte file. The former is another tar archive, the content of that archive is the following: | * "update.pua": This is the firmware update data for the Kart. This is a tar archive. The extracted archive contains "update.pui" and "pui.hash". The latter is a binary 0x100-byte file. The former is another tar archive, the content of that archive is the following: | ||
Line 47: | Line 49: | ||
The only changes in the OSS for 1.0.0_1 -> 1.1.0_3 are the following (note that there are more versions between these): | The only changes in the OSS for 1.0.0_1 -> 1.1.0_3 are the following (note that there are more versions between these): | ||
* The following archives were updated: linux-kernel, PsdDriver, rtl8188eu, uboot. | * The following archives were updated: linux-kernel, PsdDriver, rtl8188eu, uboot. | ||
* In the PsdDriver source, the line-ending at the start of various source files was updated. | * In the PsdDriver source, the line-ending at the start of various source files was updated. | ||
Line 58: | Line 61: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Component | |||
!Manufacturer | |||
!Part | |||
!Notes | |||
|- | |- | ||
|SoC | |||
|Realtek | |||
|RTD1195 (PB) | |||
|Contains hardware H.264 encoder | |||
|- | |- | ||
| | |DDR3 RAM | ||
| | |Winbond | ||
| | |W631GG6MB-15 | ||
| | |128 MiB | ||
|- | |- | ||
| | |NAND Flash | ||
| Winbond | |Winbond | ||
| | |W29N01HVSINA | ||
| 128 MiB | |128 MiB | ||
|- | |- | ||
| | |WNIC | ||
| | |Realtek | ||
| | |RTL8188E | ||
| | |Connected to SoC via USB | ||
|- | |- | ||
| | |MCU | ||
| | |STMicroelectronics | ||
| | |STM32F | ||
| | |Responsible for real-time steering and throttle control loops, six-axis IMU acquisition, GPIO, battery status | ||
|- | |- | ||
| | |IMU | ||
| STMicroelectronics | |STMicroelectronics | ||
| | |LSM6DSL | ||
| | |Unconfirmed. Mounted "upside-down" on the PCB: +X=right +Y=back +Z=down. Sensitivities: 4.375 m°/s, 0.244 mg. | ||
|- | |- | ||
| | |Li-ion pouch cell | ||
| | |Nintendo branded; OEM unknown | ||
| | |HAC-038 | ||
| | |3.7V nominal; 1750 mAh capacity | ||
|- | |- | ||
|Camera | |||
|Unknown | |||
|Unknown | |||
|Possibly connected via MIPI CSI | |||
| Camera | |||
| Unknown | |||
| Unknown | |||
| Possibly connected via MIPI CSI | |||
|} | |} | ||
Line 115: | Line 117: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x10 | |||
|Pairing seed. LP2P PSK is SHA256(seed) | |||
|- | |- | ||
|0x10 | |||
|0x20 | |||
|Pairing SSID. Remaining space is filled with zeros. | |||
|- | |- | ||
| | |0x30 | ||
|0x2 | |||
|Pairing channel. Encoded little-endian. Usually 0. | |||
|- | |- | ||
| | |0x32 | ||
| | |0xC | ||
|Padding bytes; zero. | |||
|} | |} | ||
Line 133: | Line 142: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|+ Summary of ports | |+Summary of ports | ||
!Protocol | |||
!Endpoint | |||
!Port | |||
!Description | |||
![[RCD]] service ID | |||
|- | |- | ||
! | ! colspan="5" |Management | ||
|- | |- | ||
| rowspan="5" |TCP | |||
| rowspan="2" |Switch | |||
|5201 | |||
|[[RCD#Handshake protocol|RCD handshake]] service (pairing only) | |||
|0x0001 | |||
|- | |- | ||
| | |5202 | ||
|RCD handshake service (non-pairing only) | |||
|0x0001 | |||
| 0x0001 | |||
|- | |- | ||
| | | rowspan="3" |Kart | ||
| RCD | |5103 | ||
| | |"Fuji Control" RCD service | ||
|0x0100 | |||
|- | |- | ||
| | |5106 | ||
|"Fuji Pairing" RCD service (pairing only) | |||
| "Fuji | |0x0102 | ||
| | |||
|- | |- | ||
| | |5107 | ||
| "Fuji | |"Fuji Update" RCD service | ||
| | |0x0103 | ||
|- | |- | ||
| | |UDP | ||
| | |Kart | ||
| | |5004 | ||
|Time synchronization | |||
|N/A | |||
|- | |- | ||
| | ! colspan="5" |Video | ||
|- | |- | ||
|UDP | |||
| rowspan="2" |Switch | |||
|5016+kartid | |||
|"LSP" video streaming | |||
|N/A | |||
|- | |- | ||
| | |TCP | ||
| | |5032+kartid | ||
|"LSP" control channel | |||
| "LSP" | |N/A (non-RCD) | ||
| N/A | |||
|- | |- | ||
! colspan="5" |Control | |||
| | |||
|- | |- | ||
| rowspan="2" |UDP | |||
|Kart | |||
|5102 | |||
|Teleoperation (throttle, steering, tail light control) | |||
|N/A | |||
|- | |- | ||
|Switch | |||
|5116+kartid | |||
|Telemetry | |||
|N/A | |||
| Switch | |||
| 5116+kartid | |||
| Telemetry | |||
| N/A | |||
|} | |} | ||
Line 215: | Line 223: | ||
Accepts a 0x40-byte payload: | Accepts a 0x40-byte payload: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x00 | |||
|0x20 | |||
|SSID, zero-terminated. ''Home Circuit'' copies this straight from GroupInfo, so uninitialized bytes may follow. | |||
| 0x00 | |||
| 0x20 | |||
| SSID, zero-terminated. ''Home Circuit'' copies this straight from GroupInfo, so uninitialized bytes may follow. | |||
|- | |- | ||
| 0x20 | |0x20 | ||
| 0x20 | |0x20 | ||
| LP2P PSK | |LP2P PSK | ||
|} | |} | ||
Line 240: | Line 247: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x1 | |||
|boot_major_version | |||
| 0x0 | |||
| 0x1 | |||
| boot_major_version | |||
|- | |- | ||
| 0x1 | |0x1 | ||
| 0x1 | |0x1 | ||
| boot_minor_version | |boot_minor_version | ||
|- | |- | ||
| 0x2 | |0x2 | ||
| 0x1 | |0x1 | ||
| system_major_version | |system_major_version | ||
|- | |- | ||
| 0x3 | |0x3 | ||
| 0x1 | |0x1 | ||
| system_minor_version | |system_minor_version | ||
|- | |- | ||
| 0x4 | |0x4 | ||
| 0x29 | |0x29 | ||
| Zero-terminated ASCII string which is a 160-bit value in hexadecimal. Appears to be some kind of SHA1. | |Zero-terminated ASCII string which is a 160-bit value in hexadecimal. Appears to be some kind of SHA1. | ||
|} | |} | ||
Line 271: | Line 277: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x80 | |||
|Parameter name, zero-padded. | |||
|- | |- | ||
| | |0x80 | ||
| | |0x2 | ||
| | |Value length | ||
|- | |- | ||
| | |0x82 | ||
| | |0xE | ||
| | |Zero padding to align to 0x10-byte boundary | ||
|- | |- | ||
|0x90 | |||
|Varies | |||
|Value to set | |||
| 0x90 | |||
| Varies | |||
| Value to set | |||
|} | |} | ||
Line 296: | Line 301: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x2 | |||
|Fixed 0x0001; unknown purpose. | |||
|- | |- | ||
| | |0x2 | ||
| 0x2 | |0x2 | ||
| | |Telemetry (UDP) port on Switch | ||
|- | |- | ||
| | |0x4 | ||
| 0x2 | |0x2 | ||
| | |"LSP" control (TCP) port on Switch | ||
|- | |- | ||
| | |0x6 | ||
| 0x2 | |0x2 | ||
| "LSP" | |"LSP" video (UDP) port on Switch | ||
|- | |- | ||
|0x8 | |||
|0x8 | |||
|Current network time, per nn::time::StandardNetworkSystemClock::GetCurrentTime. (A Unix timestamp with one-second precision.) | |||
| 0x8 | |||
| 0x8 | |||
| Current network time, per nn::time::StandardNetworkSystemClock::GetCurrentTime. (A Unix timestamp with one-second precision.) | |||
|} | |} | ||
Line 327: | Line 331: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |||
|0x00 | |||
|0x80 | |||
|Parameter name, zero-padded. | |||
|} | |||
One of the known parameters is "product_code" which includes the kart's character as 1 byte, and includes a string with the value of the kart's serial number on the bottom of the kart (white-label barcode). | |||
{| class="wikitable" border="1" | |||
!Offset | |||
!Size | |||
!Description | |||
|- | |||
|0x00 | |||
|0x80 | |||
|Fixed 0x010000; unknown purpose | |||
|- | |- | ||
|0x3 | |||
|0x1 | |||
|Fixed 0x03; unknown purpose | |||
|- | |- | ||
| | |0x7 | ||
| | |0x1 | ||
| | |Fixed 0x24; unknown purpose | ||
|- | |||
|0xC | |||
|0x1 | |||
|Fixed 0x01; unknown purpose | |||
|- | |||
|0x11 | |||
|0x1 | |||
|Fixed 0x14; unknown purpose | |||
|- | |||
|0x20 | |||
|0x2 | |||
|Fixed 0x0100; padding | |||
|- | |||
|0x22 | |||
|0x1 | |||
|Character ID; 0x01 = Mario, 0x02 = Luigi, unknown if there are other "hidden" characters | |||
|- | |||
|0x23 | |||
|0x2 | |||
|Fixed 0x0001; padding | |||
|- | |||
|0x24 | |||
|0xF | |||
|Kart Serial Number; | |||
'''X''': Nintendo Switch Platform | |||
'''Q''': Hardware Identifier for the Mario Kart Live: Home Circuit kart. | |||
'''J'''/'''W''': Factory Location; Either '''W''': US, or '''J''': Japan | |||
'''10'''/'''14'''/'''40'''/'''70:''' Factory Number | |||
'''Last 9 Numbers''': Unit Number | |||
|} | |} | ||
==== Command 0x04: SetState ==== | ==== Command 0x04: SetState ==== | ||
Line 344: | Line 398: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x1 | |||
|Drive mode. 0x01 enables driving controls (and video), 0x00 puts the kart to "sleep." | |||
| 0x0 | |||
| 0x1 | |||
| Drive mode. 0x01 enables driving controls (and video), 0x00 puts the kart to "sleep." | |||
|- | |- | ||
| 0x1 | |0x1 | ||
| 0xF | |0xF | ||
| Zero padding. | |Zero padding. | ||
|} | |} | ||
Line 374: | Line 427: | ||
=== Teleoperation === | === Teleoperation === | ||
The kart is operated over UDP port 5102. This port is only open when the kart is in [[#Command 0x04: SetState|drive state]]. It expects packets of the form: | The kart is operated over UDP port 5102. This port is only open when the kart is in [[User:Joel Osler/sandbox#Command 0x04: SetState|drive state]]. It expects packets of the form: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x1 | |||
|Throttle; a signed integer. -128 is full-speed reverse, +127 is full-speed forward. | |||
| 0x0 | |||
| 0x1 | |||
| Throttle; a signed integer. -128 is full-speed reverse, +127 is full-speed forward. | |||
|- | |- | ||
| 0x1 | |0x1 | ||
| 0x1 | |0x1 | ||
| Steering; a signed integer. -128 is full left, +127 is full right. | |Steering; a signed integer. -128 is full left, +127 is full right. | ||
|- | |- | ||
| 0x2 | |0x2 | ||
| 0x1 | |0x1 | ||
| Brake light control. 0x00 turns the brake light off, 0x01 turns it on. This is independent of throttle. | |Brake light control. 0x00 turns the brake light off, 0x01 turns it on. This is independent of throttle. | ||
|- | |- | ||
| 0x3 | |0x3 | ||
| 0x1 | |0x1 | ||
| Pad byte, apparently always zero. | |Pad byte, apparently always zero. | ||
|- | |- | ||
| 0x4 | |0x4 | ||
| 0x4? | |0x4? | ||
| Little-endian packet counter. Incremented by 1 for each sent packet. Unknown total size. | |Little-endian packet counter. Incremented by 1 for each sent packet. Unknown total size. | ||
|- | |- | ||
| 0x8? | |0x8? | ||
| 0x18? | |0x18? | ||
| Zero padding to bring the total packet size to 0x20. | |Zero padding to bring the total packet size to 0x20. | ||
|} | |} | ||
Line 422: | Line 474: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
!Description | |||
|- | |- | ||
|0x0 | |||
|0x3 | |||
|Zero padding | |||
| 0x0 | |||
| 0x3 | |||
| Zero padding | |||
|- | |- | ||
| 0x3 | |0x3 | ||
| 0x1 | |0x1 | ||
| How many bars to show in the HUD for battery status (0x00-0x04) | |How many bars to show in the HUD for battery status (0x00-0x04) | ||
|- | |- | ||
| 0x4 | |0x4 | ||
| 0x1C | |0x1C | ||
| Zero padding, to bring total packet length to 0x20. | |Zero padding, to bring total packet length to 0x20. | ||
|} | |} | ||
Line 449: | Line 500: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
!Offset | |||
!Size | |||
! colspan="2" |Description | |||
|- | |- | ||
|0x0 | |||
|0x2 | |||
| colspan="2" |Total IMU samples, as an unsigned integer. This number includes the samples in this packet. It overflows. | |||
| 0x0 | |||
| 0x2 | |||
|colspan="2"| Total IMU samples, as an unsigned integer. This number includes the samples in this packet. It overflows. | |||
|- | |- | ||
| 0x2 | |0x2 | ||
| 0x1 | |0x1 | ||
|colspan="2"| Flags bitfield: PCCCCNNN. P=High-precision, C=Unknown, possibly clipping indicators. N=Number of IMU samples. | | colspan="2" |Flags bitfield: PCCCCNNN. P=High-precision, C=Unknown, possibly clipping indicators. N=Number of IMU samples. | ||
|- | |- | ||
| 0x3 | |0x3 | ||
| 0x1 | |0x1 | ||
|colspan="2"| Pad byte; zero. | | colspan="2" |Pad byte; zero. | ||
|- | |- | ||
| 0x4 | |0x4 | ||
| 0x4 | |0x4 | ||
|colspan="2"| Microsecond-precision timer, as an unsigned integer. | | colspan="2" |Microsecond-precision timer, as an unsigned integer. | ||
|- | |- | ||
| 0x8 | |0x8 | ||
| 0x10 | |0x10 | ||
|colspan="2"| Orientation: s32 qi, qj, qk, qr; gives the coefficients of a quaternion. Units appear to be increments of 2^-30, but quaternions should always be normalized before use. | | colspan="2" |Orientation: s32 qi, qj, qk, qr; gives the coefficients of a quaternion. Units appear to be increments of 2^-30, but quaternions should always be normalized before use. | ||
|- | |- | ||
| 0x18 | |0x18 | ||
| 0xC | |0xC | ||
| Integrator A position | |Integrator A position | ||
|rowspan="2"| s32 x, y, z; gives an estimate of total displacement since this integrator was reset. Units: 24.59 * 2^-19 m(???) | | rowspan="2" |s32 x, y, z; gives an estimate of total displacement since this integrator was reset. Units: 24.59 * 2^-19 m(???) | ||
|- | |- | ||
| 0x24 | |0x24 | ||
| 0xC | |0xC | ||
| Integrator B position | |Integrator B position | ||
|- | |- | ||
| 0x30 | |0x30 | ||
| 0xC | |0xC | ||
| Integrator A velocity | |Integrator A velocity | ||
|rowspan="2"| s32 x, y, z; gives an estimate of total change in velocity since this integrator was reset. Units: ~2^-19 m/s | | rowspan="2" |s32 x, y, z; gives an estimate of total change in velocity since this integrator was reset. Units: ~2^-19 m/s | ||
|- | |- | ||
| 0x3C | |0x3C | ||
| 0xC | |0xC | ||
| Integrator B velocity | |Integrator B velocity | ||
|- | |- | ||
|rowspan="2"| 0x48 | | rowspan="2" |0x48 | ||
|rowspan="2"| 0xC*(NNN+1) | | rowspan="2" |0xC*(NNN+1) | ||
|rowspan="2"| 1-8 raw IMU samples | | rowspan="2" |1-8 raw IMU samples | ||
| s16 accel_x, accel_y, accel_z; // in units of 0.000244 Gs. 1G is added to accel_z to compensate for gravity. | |s16 accel_x, accel_y, accel_z; // in units of 0.000244 Gs. 1G is added to accel_z to compensate for gravity. | ||
|- | |- | ||
| s16 ang_vel_x, ang_vel_y, ang_vel_z; // in units of 0.004375 degrees per second. | |s16 ang_vel_x, ang_vel_y, ang_vel_z; // in units of 0.004375 degrees per second. | ||
|} | |} | ||
Line 523: | Line 573: | ||
ExeFs: | ExeFs: | ||
* Nothing changed besides the usual NPDM update. | * Nothing changed besides the usual NPDM update. | ||
RomFs: | RomFs: | ||
* Only update.pua was updated, the following was changed in the extracted update.pui (pui.hash in update.pua was also updated): | * Only update.pua was updated, the following was changed in the extracted update.pui (pui.hash in update.pua was also updated): | ||
** "config.txt": system_minor_version was changed from "3" to "4". | ** "config.txt": system_minor_version was changed from "3" to "4". |