aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/pictochat-msg-crop-lork2.pngbin0 -> 3794 bytes
-rw-r--r--assets/pictochat-msg-crop.pngbin0 -> 1374 bytes
-rw-r--r--assets/pictochat-msg-height-1-4.pngbin0 -> 2272 bytes
-rw-r--r--assets/pictochat-msg-height-5-draw.pngbin0 -> 1185 bytes
-rw-r--r--assets/pictochat-msg-pattern.pngbin0 -> 3878 bytes
-rw-r--r--assets/ws-msg-pattern.pngbin0 -> 162965 bytes
-rw-r--r--docs/notes.md69
-rwxr-xr-xexperiments/pixel-sequence/draw31
-rw-r--r--wireshark/nifi.lua7
-rw-r--r--wireshark/pictochat.lua14
-rw-r--r--wireshark/readme.md4
-rwxr-xr-xwireshark/wireshark8
12 files changed, 125 insertions, 8 deletions
diff --git a/assets/pictochat-msg-crop-lork2.png b/assets/pictochat-msg-crop-lork2.png
new file mode 100644
index 0000000..a4e6390
--- /dev/null
+++ b/assets/pictochat-msg-crop-lork2.png
Binary files differ
diff --git a/assets/pictochat-msg-crop.png b/assets/pictochat-msg-crop.png
new file mode 100644
index 0000000..f332f78
--- /dev/null
+++ b/assets/pictochat-msg-crop.png
Binary files differ
diff --git a/assets/pictochat-msg-height-1-4.png b/assets/pictochat-msg-height-1-4.png
new file mode 100644
index 0000000..25d22a5
--- /dev/null
+++ b/assets/pictochat-msg-height-1-4.png
Binary files differ
diff --git a/assets/pictochat-msg-height-5-draw.png b/assets/pictochat-msg-height-5-draw.png
new file mode 100644
index 0000000..1910d83
--- /dev/null
+++ b/assets/pictochat-msg-height-5-draw.png
Binary files differ
diff --git a/assets/pictochat-msg-pattern.png b/assets/pictochat-msg-pattern.png
new file mode 100644
index 0000000..db19ad2
--- /dev/null
+++ b/assets/pictochat-msg-pattern.png
Binary files differ
diff --git a/assets/ws-msg-pattern.png b/assets/ws-msg-pattern.png
new file mode 100644
index 0000000..d1f08ef
--- /dev/null
+++ b/assets/ws-msg-pattern.png
Binary files differ
diff --git a/docs/notes.md b/docs/notes.md
index 21eef78..657383e 100644
--- a/docs/notes.md
+++ b/docs/notes.md
@@ -81,16 +81,81 @@ sufficiently advanced local multiplayer emulation.
source: <https://git.pipeframe.xyz/fork/melonDS>
-### Findings
-
- melonDS @ Config > Wifi settings "Local multiplayer features do not use the same network protocols as online play"
- comment @ src/Wifi.cpp:46 "multiplayer host TX sequence"
- references to `RFTransfer_Type{2,3}` @ <https://www.problemkaputt.de/gbatek.htm#dswifirfchip>
- nintendo ds ni-fi protocol @ <https://web.archive.org/web/20090202194241/http://masscat.afraid.org/ninds/proto_info.php>
- melonDS emulates actual 802.11b frames
- the protocol does not appear to be encrypted:
+
![](../assets/ws-no-encrypt.png)
+
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
+ up a constant stream, and messages are sent across multiple frames.
+- 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
+ message content
+
+### Message sizing/cropping
+
+- PictoChat automatically crops messages to the smallest height (at the fixed
+ intervals shown as notebook lines in the edit field on the bottom screen).
+ Message content can be on the line itself without causing the cropping
+ algorithm to 'allocate' more space; the allocation only happens if any of the
+ pixels on the line *below* the colored line are used. The method used to crop
+ the messages also ensures that the username label in the top left does not
+ obstruct or remove any content.
+
+ ![](../assets/pictochat-msg-height-1-4.png)
+ ![](../assets/pictochat-msg-height-5-draw.png)
+- Message content is likely only cropped when displaying
+
+ ![](../assets/pictochat-msg-crop.png)
+ ![](../assets/pictochat-msg-crop-lork2.png)
+
+ The above image was obtained after the following steps:
+ - Fill in the top row of the message with the black pen, ensuring the entire
+ notebook line is colored in as well
+ - Send message (displayed as top message)
+ - Copy message
+ - Erase small portion of black area on the right side (displayed as bottom message)
+
+ Notable observations:
+ - The message content has a 1 pixel border (padding/margin) on all sides
+ (except the bottom and corners) that can not be filled in. The bottom
+ border is correctly displayed for received messages, but the edit field has
+ an additional row of pixels that directly touch the message border on the
+ bottom.
+ - When any message is cloned, additional pixels that were masked on the top
+ screen become visible again in the edit field. This includes the bottom row
+ of pixels, as well as the two rows of pixels shown in the single line
+ message picture.
+
+### Message content
+
+![](../assets/pictochat-msg-pattern.png)
+![](../assets/ws-msg-pattern.png)
+
+- All messages with interesting content have NIFI 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
+ 0xe004 at offset 0x0026, while resends have a value of 0xf000 instead.
+- There are a lot of messages with length 0xaa (170), these appear to include a
+ random 32-bit value at offset 0x0046.
+- The message content (suspected bitmap-like format) appears to be sent
+ unencrypted (patterns of 0x0 and 0x1 nibbles clearly visible in hexdump).
+
+## Unsure/notes
+
+- Is the endianness of the DS properly emulated?
+- Is the NIFI 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?
+
diff --git a/experiments/pixel-sequence/draw b/experiments/pixel-sequence/draw
new file mode 100755
index 0000000..c26ac27
--- /dev/null
+++ b/experiments/pixel-sequence/draw
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# pray that the mouse is in the edit field once this timer runs out
+sleep 3
+
+pattern='
+1010
+11001100
+1111000011110000
+11111111000000001111111100000000
+'
+pattern="$(echo "$pattern" | tr -d '\n' | sed 's/./\0 /g')"
+
+for pixel in $pattern ; do
+ # shift mouse 1 pixel right
+ xdotool mousemove_relative 1 0
+
+ # skip 0's in $pattern
+ [ $pixel -ne 1 ] && continue
+
+ # drag mouse 1px down to create pixel
+ xdotool mousedown 1
+ sleep 0.05
+ xdotool mousemove_relative 0 5
+ sleep 0.05
+ xdotool mouseup 1
+ sleep 0.05
+ xdotool mousemove_relative 0 -5
+ sleep 0.05
+done
+
diff --git a/wireshark/nifi.lua b/wireshark/nifi.lua
index d81ff31..2bc96a6 100644
--- a/wireshark/nifi.lua
+++ b/wireshark/nifi.lua
@@ -1,6 +1,3 @@
--- NOTE: my system is little-endian, so the .pcap files and this decoder expect
--- little endian
-
local nifi = Proto("nifi", "Nintendo DS ni-fi")
nifi.fields.magic = ProtoField.uint32("nifi.magic", "Magic", base.HEX)
nifi.fields.senderid = ProtoField.int32("nifi.senderid", "SenderID", base.DEC)
@@ -21,7 +18,7 @@ local nifi_type_enum_field = Field.new("nifi.type.enum")
function nifi.dissector(buffer, pinfo, tree)
-- check magic ("NIFI")
if buffer(0, 4):uint() ~= 0x4e494649 then return end
- local nifi_tree = tree:add(nifi, buffer(), "Ni-Fi data")
+ local nifi_tree = tree:add(nifi, buffer(0, 24), "Ni-Fi data")
nifi_tree:add(nifi.fields.magic, buffer(0, 4))
nifi_tree:add_le(nifi.fields.senderid, buffer(4, 4))
@@ -36,5 +33,7 @@ function nifi.dissector(buffer, pinfo, tree)
pinfo.cols.protocol = nifi.name
pinfo.cols.src = nifi_senderid_field().display
pinfo.cols.info = "type:" .. nifi_type_enum_field().display
+
+ return 24
end
diff --git a/wireshark/pictochat.lua b/wireshark/pictochat.lua
new file mode 100644
index 0000000..5eb8089
--- /dev/null
+++ b/wireshark/pictochat.lua
@@ -0,0 +1,14 @@
+local pc = Proto("pictochat", "Nintendo DS PictoChat")
+
+function pc.dissector(buffer, pinfo, tree)
+
+ local pc_tree = tree:add(pc, buffer(), "PictoChat Message")
+
+ pinfo.cols.protocol = pc.name
+
+end
+
+-- no worky
+local nifi = DissectorTable.get("nifi.length")
+nifi:add('>0', pc)
+
diff --git a/wireshark/readme.md b/wireshark/readme.md
new file mode 100644
index 0000000..dfebf83
--- /dev/null
+++ b/wireshark/readme.md
@@ -0,0 +1,4 @@
+## notes
+
+- my system is little-endian, so the .pcap files and this decoder expect little
+ endian
diff --git a/wireshark/wireshark b/wireshark/wireshark
index 42c37a5..ee24518 100755
--- a/wireshark/wireshark
+++ b/wireshark/wireshark
@@ -1,5 +1,9 @@
#!/bin/sh
-# simple wrapper to load nifi.lua script as DLT_USER0 dissecter
+# simple wrapper to load lua scripts for DLT_USER0
here="$(dirname "$0")"
-exec wireshark -X "lua_script:$here/nifi.lua" -o 'uat:user_dlts:"User 0 (DLT=147)","nifi","","","",""' "$@"
+exec wireshark \
+ -X "lua_script:$here/nifi.lua" \
+ -X "lua_script:$here/pictochat.lua" \
+ -o 'uat:user_dlts:"User 0 (DLT=147)","nifi","","","",""' \
+ "$@"