Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@iracigt
Created May 1, 2021 22:19
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save iracigt/50b3a857e4d82c2c11d0dd5f84ecac6b to your computer and use it in GitHub Desktop.
Save iracigt/50b3a857e4d82c2c11d0dd5f84ecac6b to your computer and use it in GitHub Desktop.
Nintendo Wireless Adapter Specification v1.1 by denopqrihg
Nintendo Wireless Adapter Specification
v1.1 (23th June 2005)
by denopqrihg (denopqrihg@centrum.cz)
This document describes how a GBA program can communicate with a plugged-in Nintendo wireless adapter. This info is not 100% accurate, nor am I responsible for any damage it may do. I am only sharing my partial knowledge.
Some general info
-----------------
The Nintendo Wireless Adapter is a device that presents more multiplayer features than the link cable. It uses a kind of server/client approach (broadcasting, connections etc.). It allows to send quite large amounts of data at once (most I've seen was 80 bytes), has built-in synchronisation and much more.
This document is only about two player link. At the moment, I have no info about how it works with mre players.
If you don't understand something in this document or think something is unclear, contact me and I'll try to clarify.
Which mode to use?
------------------
32-bit Normal mode, all the time. No exceptions.
Mostly 2Mbit internal clock, but there are exceptions which will be pointed out.
Initialization
--------------
Use: 32-bit Normal mode, 256Khz internal clock.
Send the text "NINTENDO/0x01/0x80" in the following manner:
Store two bytes of the text in the lower 16 bits of the send data. The upper 16 bits should be 1's complement of the previously received lower 16 bits. Send it. Received data should look like the one you sent, except that the upper and lower halfword are swapped. Repeat this process until you have sent the whole string (the last two bytes are 0x8001).
Example:
Send Receive
0xgggg494e 0x494egggg
0xb6b1494e 0x494eb6b1
0xb6b1544e 0x544eb6b1
0xabb1544e 0x544eabb1
0xabb14e45 0x4e45abb1
0xb1ba4e45 0x4e45b1ba
0xb1ba4f44 0x4f44b1ba
0xb0bb4f44 0x4f44b0bb
0xb0bb8001 0x8001b0bb
(gggg = garbage)
Then send command 0x3d or 0x10, difference is unknown (what is a command and how to use it is in the next section).
Communication
-------------
The adapter uses a form of communication that I call 'commands'.
It waits until you send a command to it, and then it does something according to what command you sent.
The format is:
0x9966wwcc
cc is the 1-byte command
ww is a number indicating how many 4-byte units of data will follow the command (I don't know what happens when you send data with a command that shouldn't send any).
When you send this, you always receive 0x80000000 (also when sending the additional data).
Then, you must send 0x80000000. You then receive a similar structure, 0x9966wwaa.
ww is again a number of words (4 byte) following this command
aa is the command you sent ORed with 0x80 (with some exceptions)
If there was a nonzero word count in the response, send 0x80000000 the apropriate number of times and store the data you receive (you requested it, so you should store it).
Remember to keep some delays between transfers.
Example:
Send Receive
0x99660117 0x80000000
0x003c0720 0x80000000
0x80000000 0x99660097
Another example:
Send Receive
0x9966001a 0x80000000
0x80000000 0x9966019a
0x80000000 0x00001547
Ackowledging
------------
After each transfer (except initialization), a kind of 'acknowledge procedure' must be done (maybe it isn't necessary, but the games do it):
Right after the transfer ends, output SO=low, wait until SI becomes high, then output SO=high and wait until SI=low.
!! Exception !! After commands 0xa5 and 0xa7, the polarity is 'swapped': output SO=low, wait until SI=low, then send SO=high and wait until SI=high
Also, just before each transfer, set SO=low
(This part is a bit unclear to me, maybe it doesn't work like this at all)
Commands
-----------------
Many commands have completely unknown function, some of them must be sent but nobody knows why and what they mean.
This is not a complete list of commands, I only listed the commands that either are important or I know something about them.
I will use the following notation:
Command number
--------------
S: how many words to send
R: how many words to receive
Description of what the command does (if known :-)
0x10
----
S: 0
R: 0
Last step of initialization, difference between this and 0x3d is unknown, both are used
0x10 seems to be 'safer'
0x11
----
S: 0
R: 1
This command always receives 0xff in 2 player link, maybe it has to do with 3+ players ??
0x13
----
S: 0
R: 1
Receives a random value, don't know what it's for
0x16
----
S: usually 6
R: 0
Sends 'broadcast' data, which will be received by all adapters in range
0x17
----
S: 1
R: 0
Setup?? The value sent should be 003d0620 (Digimon), 003c0420 (Pokemon) or something along this way.
0x1a
----
S: 0
R: 0 or 1
This command is used by the 'server' to check if someone wants to connect. If not, no data is received. If yes, you'll get a value (random? or ID?)
0x1d
0x1e
----
S: 0
R: multiples of 7 (usually)
Read 'broadcast' data. Data from each adapter is prefixed by one word containing an 'ID' of the adapter , which is used when you want to connect.
0x1f
----
S: 1
R: 0
Connect to server. Value sent is the 'ID' of the adapter you want to connect to.
0x20
----
S: 0
R: 1
Used after 0x1f, generally resend until highest byte is 0.
0x21
----
S: 0
R: 1
Send once after 0x20 successfully finished (returned 0).
0x24
----
S: anything
R: 0
Send data to connected adapters (I've only seen this command used by servers, but maybe clients can use it as well)
0x25
----
S: anything
R: 0
Same as 0x24, with the exception that this command 'waits' until incoming data is available.
This keeps the games synchronized without any further in-game programming.
How to use: After you send all the data and get 0x996600a5 from the adapter, store 0x80000000 in the send data register and start a transfer with _EXTERNAL_ clock. Once the data arrives, you'll receive a 0x99660028 command (which you have to ackowledge just like the adapter - send back 0x996600a8).
Also note that after you receive the 0x996600a5 until you use the next command (usually 0x26), the polarity of the SI and SO conmfirmation procedure is swapped.
0x26
----
S: 0
R: anything
Receive data.
0x27
----
S: 0
R: 0
Similar to 0x25, but without sending data. All strange behavior of 0x25 applies here, too.
0x30
----
S: 1?
R: 0
Most likely a 'Terminate connection' command. Data value is usually 1.
0x3d
----
S: 0
R: 0
Same as 0x10
0xa8
----
S: 0
R: 0
Ackowledge of 0x28 sent by adapter.
0xee
----
S: 1?
R: 0
This is very unconfirmed, but is probably used when you want the adapter to resend the last command/whatever ??
Example
-------------
A complete example of a client/server communication
(all numbers are in hex)
Server
------
value of
0x128 reg Send Receive
5084 00000000 garbage
5085 ffff494e 494egggg
5085 b6b1494e 494eb6b1
5085 b6b1544e 544eb6b1
5085 abb1544e abb1544e
5085 abb14e45 4e45abb1
5085 b1ba4e45 4e45b1ba
5085 b1ba4f44 4f44b1ba
5085 b0bb4f44 4f44b0bb
5085 b0bb8001 8001b0bb
5003
5083 99660010 80000000
500b
5003
5083 80000000 99660090
500b
5003
5083 99660117 80000000
500b
5003
5083 003c0420 80000000
500b
5003
5083 80000000 99660097
500b
5003
5003
5083 99660616 80000000
500b
5003
5083 0c020002 80000000
500b
5003
5083 00005ce1 80000000
500b
5003
5083 00000000 80000000
500b
5003
5083 09000040 80000000
500b
5003
5083 c1cfc8cd 80000000
500b
5003
5083 00ffccbb 80000000
500b
5003
5083 80000000 99660096
500b
5003
5083 99660013 80000000
500b
5003
5083 80000000 99660193
500b
5003
5083 80000000 02001234 (example)
500b
5003
5083 99660019 80000000
500b
5003
5083 80000000 99660099
500b
|------------------------------------------------
v |
5003 |
5083 9966001a 80000000 |
500b |
5003 |
5083 80000000 9966009a |
500b |
repeat ------------------------------------------
until you get
|----------------------------------------------------------------
v |
5003 |
5083 9966001a 80000000 |
500b |
5003 |
5083 80000000 9966019a |
5003 |
5083 80000000 00004875 (example) |
500b |
5003 |
5083 99660011 80000000 |
500b |
5003 |
5083 80000000 99660191 |
500b |
5003 |
5083 80000000 000000ff |
500b |
repeat a few times to ensure that it really is a connection -----
5003
5083 99660124 80000000
500b
5003
5083 12345678 80000000
500b
5003
5083 80000000 99660094
500b
|------------------------------------------------
v |
5003 |
5083 99660026 80000000 |
500b |
5003 80000000 996600a6 |
500b |
repeat until you get some data -----------------
send & receive etc. etc.
Most games switch to 0x25 for the server as well after a while.
when you want to exit
5003
5083 99660130 80000000
500b
5003
5083 00000001 80000000
500b
5003
5083 80000000 996600b0
500b
Client
------
value of
0x128 reg Send Receive
5084 00000000 garbage
5085 ffff494e 494egggg
5085 b6b1494e 494eb6b1
5085 b6b1544e 544eb6b1
5085 abb1544e abb1544e
5085 abb14e45 4e45abb1
5085 b1ba4e45 4e45b1ba
5085 b1ba4f44 4f44b1ba
5085 b0bb4f44 4f44b0bb
5085 b0bb8001 8001b0bb
5003
5083 99660010 80000000
500b
5003
5083 80000000 99660090
500b
5003
5083 99660117 80000000
500b
5003
5083 003c0420 80000000
500b
5003
5083 80000000 99660097
500b
5003
5003
5083 99660616 80000000
500b
5003
5083 0c020002 80000000
500b
5003
5083 00005ce1 80000000
500b
5003
5083 00000000 80000000
500b
5003
5083 09000040 80000000
500b
5003
5083 c1cfc8cd 80000000
500b
5003
5083 00ffccbb 80000000
500b
5003
5083 80000000 99660096
500b
|------------------------------------------------------------------------
v |
5003 |
5083 99660017 80000000 |
500b |
5003 |
5083 80000000 99660797 |
500b |
5003 |
5083 80000000 00002154 adapter's ID |
500b |
5003 |
5083 80000000 0c020002 |
500b |
5003 |
5083 80000000 00005ce1 |
500b |
5003 |
5083 80000000 00000000 |
500b |
5003 |
5083 80000000 09000040 |
500b |
5003 |
5083 80000000 c1cfc8cd |
500b |
5003 |
5083 80000000 00ffccbb |
500b |
repeat, display available servers and wait until the player picks one ---
5003
5083 9966011f 80000000
500b
5003
5083 00002154 80000000 pass the ID of the appropriate adapter
500b
5003
5083 80000000 9966009f
500b
|------------------------------------------------
v |
5003 |
5083 99660020 80000000 |
500b |
5003 |
5083 80000000 996601a0 |
500b |
5003 |
5083 80000000 00001567 |
500b if highest byte wasn't 0, repeat --------
5003
5083 99660021 80000000
500b
5003
5083 80000000 996600a1
500b
5003
5083 99660027 80000000
500b
5003
5083 80000000 996600a7 now you wait until SI = SO, not the other way around
500b
5002
5082 80000000 99660028 !! EXTERNAL clock
500a
5002
5082 996600a8 80000000
500a
5003
5083 99660026 80000000 up till now
500b
5003
5083 80000000 996601a6
500b
5003
5083 80000000 12345678
500b
5003
5083 996602a5 80000000
500b
5003
5083 87654321 80000000
500b
5003
5083 45678123 80000000
500b
5003
5083 80000000 996600a5 here again, SI = SO
500b
5002
5082 80000000 99660028 !! EXTERNAL clock
500a
5002
5082 996600a8 80000000
500a
5003
5083 99660026 80000000 from here it's normal
etc. etc.
when you want to exit
5003
5083 99660130 80000000
500b
5003
5083 00000001 80000000
500b
5003
5083 80000000 996600b0
500b
Thanks to
---------
Lizardon for trying out my 'pimped' ROMS on his adapter
Nintendo for not giving away ANY info on this thing :-( (at least it was nice practice to figure it out)
You for reading the whole example
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment