diff options
author | lonkaars <loek@pipeframe.xyz> | 2024-05-02 16:58:35 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2024-05-02 16:58:35 +0200 |
commit | 1634d546d3e941701fdbab211dfa376f334339f1 (patch) | |
tree | 16aaba7f0d0b529fb6793809e1c05b87770c9b87 /docs | |
parent | 7c402c347b46f908eefefb6a957bf92100061951 (diff) |
WIP messy pictochat protocol dissector
Diffstat (limited to 'docs')
-rw-r--r-- | docs/notes.md | 91 |
1 files changed, 74 insertions, 17 deletions
diff --git a/docs/notes.md b/docs/notes.md index 10c2608..6e515f9 100644 --- a/docs/notes.md +++ b/docs/notes.md @@ -93,10 +93,13 @@ source: <https://git.pipeframe.xyz/fork/melonDS> the string `lork` is visible as plain text in the hexdump (offset 0x0056), which appears to be some kind of 16-bit encoding of the username set on the emulator used to capture these packets -- The messages are not sent as single packets. The nifi protocol appears to set +- The messages are not sent as single packets. The Ni-Fi protocol appears to set up a constant stream, and messages are sent across multiple frames. +- A full height filled-in message results in 64 packets (with Wireshark filter + `nifi.type.enum == 1 && pictochat && frame[0x1a] == 0x02 && frame.len == + 246`) - PictoChat does not appear to send messages when you are in a chat room by - yourself, so local multiplayer / nifi emulation is required for capturing + yourself, so local multiplayer / Ni-Fi emulation is required for capturing message content ### Message sizing/cropping @@ -136,12 +139,36 @@ source: <https://git.pipeframe.xyz/fork/melonDS> message picture. - The drawable area (including obstructed top-left corner) is 228x80 pixels +Observed package counts (no resends) for messages of different sizes: +|draw area|display height|packet#| +|-|-|-| +|top-left pixel of row 1 only|1|13| +|row 1|1|13| +|row 2|2|25| +|row 3|2|25| +|rows 1-2|2|25| +|rows 1-3|3|38| +|rows 4-5|3|38| +|rows 2-3|3|38| +|rows 1-4|4|51| +|rows 1-5|5|64| +|rows 2-5|5|64| + +Notable: +- Messages that draw below line 1 while keeping line 1 empty can't be cropped + to utilize line 1 as the username label is in the way. The captured packet + counts suggest that the content of line 1 is still sent (although empty). +- The messages are cropped twice: + * (destructive) *before* sending, as suggested by the packet counts + * (non-destructive or display only) when displayed in the message log on + the top screen + ### Message content ![](../assets/pictochat-msg-pattern.png) ![](../assets/ws-msg-pattern.png) -- All messages with interesting content have NIFI header type 1 (CMD). +- All messages with interesting content have Ni-Fi header type 1 (CMD). - PictoChat messages appear to be sent over frames of length 0xf6 (246) regardless of actual message size. - All frames appear to be sent exactly 5 times. 'New' frames have a value of @@ -168,20 +195,28 @@ source: <https://git.pipeframe.xyz/fork/melonDS> |offset|type|description| |-|-|-| -|0x0000|`u32`|NIFI: Magic (0x4e494649)| -|0x0004|`u32`|NIFI: SenderID (melonDS InstanceID)| -|0x0008|`u32`|NIFI: Type| -|0x000c|`u32`|NIFI: Length (after NIFI header)| -|0x0010|`u64`|NIFI: Timestamp| +|0x00|`u32`|Ni-Fi: Magic (0x4e494649)| +|0x04|`u32`|Ni-Fi: SenderID (melonDS InstanceID)| +|0x08|`u32`|Ni-Fi: Type| +|0x0c|`u32`|Ni-Fi: Length (after Ni-Fi header)| +|0x10|`u64`|Ni-Fi: Timestamp| | -|0x0018|`u16`|PictoChat: 0| -|0x001a|`u16`|PictoChat: (Resend???) (2=New, 0=Resend)|<!-- I assume u16 because the next byte is always 0x00 --> -|0x0028|`u8[6]`|PictoChat: multiplayer CMD MAC (melonDS Wifi::MPCmdMAC)| -|0x002e|`u8[6]`|PictoChat: sender MAC| -|0x0034|`u8[6]`|PictoChat: sender MAC (again)| -|0x004d|`u8[0xa0]`|PictoChat: Message data (encoding unknown)| -|0x00ed|`u16`|PictoChat: (random???)| -|0x00f0|`u8[6]`|PictoChat: (mac/id???)| +|0x18|`u16`|PictoChat: Message type??? (0)| +|0x1a|`u16`|PictoChat: Resend (2=New, 0=Resend)|<!-- I assume u16 because the next byte is always 0x00 --> +|0x22|`u16`|PictoChat: Length (offset 36 of complete packet length)| +|0x28|`u8[6]`|PictoChat: multiplayer CMD MAC (melonDS Wifi::MPCmdMAC)| +|0x2e|`u8[6]`|PictoChat: sender MAC| +|0x34|`u8[6]`|PictoChat: sender MAC (again)| +|0x3a|`u16`|Unknown: counter| +|0x4a|`u16`|PictoChat: Message content offset| +|0x4e|`u8[0xa0]`|PictoChat: Message data (in 8x8 tiles where each byte represents two pixels as nibbles)| +|0xee|`u16`|PictoChat: packet sequence number| +|0xf0|`u16`|PictoChat: copy of 0x1a (Resend)| +|0xf2|`u32`|Unknown: constant 0x93ffb8b6| + +<!-- +TODO: 0x4e(PictoChat msg data offset) - 0x18(Ni-Fi header length) == 0x36 +--> ### Fiddling @@ -200,13 +235,35 @@ This shows a few important details: - The ordering of pixels in the messages is not reading order - Message content is not checked or validated in any way +## Room host + +The system that initially joins an empty room appears to become the room host. +This system ends up never sending messages of Ni-Fi type 2 (Reply), while the +packets from other systems after joining an existing room are sent as Ni-Fi +type 2 exclusively. + +![](../assets/ws-announce-vs.png) + +(Bottom Wireshark window is the room host, top window shows type != 2 Ni-Fi +messages from the system that joined later) + ## Unsure/notes - Is the endianness of the DS properly emulated? -- Is the NIFI magic value also present in physical frames or is this something +- Is the Ni-Fi magic value also present in physical frames or is this something MelonDS did? - The DS implemented WEP(?) encryption for connecting to home network routers/APs, but is this encryption also used when the WiFi module is used in local multiplayer mode? Does this even matter inside the emulator? +## TODO: + +- message reassembly field? (how does pictochat know which part a message index is) +- are message-resends required or can the packets be dropped? +- user identifier / login / announcement procedure? +- actual message format + * resolution + * pixel ordering + * palette color indices (pixels are 1 nibble) + |