GBA Multiplayer Serial: Controller Role, Four Result Words, and Error Recovery
Trace the Game Boy Advance's 16-bit multiplayer SIO mode from cable-selected master to ordered player words, completion flags, and safe pacing.
The Game Boy Advance link cable is not one generic “serial port” mode. The machine supports several serial interfaces, but multiplayer mode is a specific 16-bit protocol for up to four connected units. It uses a send register, four result registers, a control register, and a physical cable topology that determines which unit clocks the exchange and which units follow it. That makes the mode a useful example of hardware state that a game must coordinate before it can build its own player-selection or match protocol on top.
The register behavior below follows Nintendo’s Game Boy Advance Programming Manual, version 1.35, sections 13.2.1–13.2.4 (printed pages 113–119). The source is a scanned copy archived by the Internet Archive, not an official Nintendo-hosted developer-document URL. This is specifically the GBA’s 16-bit multiplayer mode, not the original Game Boy’s eight-bit SB/SC cable transfer, the GBA’s 8- or 32-bit normal serial modes, UART mode, or the JOY Bus.
Select the mode before treating the port as a cable link
The manual specifies multiplayer mode when RCNT bit 15 is clear and SIOCNT bits 13–12 are 10. The send word is SIOMLT_SEND at 0x0400012A. After a transfer, the four 16-bit received values appear in SIOMULTI0 through SIOMULTI3 at 0x04000120, 0x04000122, 0x04000124, and 0x04000126.
Do not reuse one mode’s register interpretation for another. SIOMLT_SEND shares an address with other serial data views, and RCNT also participates in mode selection. A trace that records only the data word but omits RCNT and SIOCNT cannot establish which serial behavior the game requested. Log those control registers with every write to the send register and every completion event.
SIOCNT also carries the interrupt-enable flag, baud-rate selection, start/busy status, communication-error status, and multiplayer ID. The manual lists multiplayer baud rates of 9,600, 38,400, 57,600, and 115,200 bits per second. Treat the selected rate as part of the transfer state; do not silently substitute a host-link speed or a frame-based delay.
The cable and connection state select master and slave
Up to four units participate. The unit whose serial input is low after the devices have entered multiplayer mode is identified as master; high input identifies a slave. The master starts a transfer by setting the start bit in SIOCNT. Its outgoing SIOMLT_SEND word is transmitted first, followed by the first, second, and third slave’s words in cable order. The connected devices do not all act as independent clock masters.
The identity number and order are not safe assumptions to make before the exchange finishes. SIOCNT bits 5–4 report the multiplayer ID at the end of communication: 00 for master, then 01, 10, and 11 for the slaves in order. Read and validate that state after completion instead of deriving player order from which device the user believes is “player one.” The link protocol reports connection order; the game remains responsible for mapping that order to its own menu and match rules.
Completion fills four slots, including missing-device sentinels
At the beginning of a master transfer, the manual says the master’s four result registers are initialized to FFFFh. Received send words are then placed in their corresponding slots: the master’s value in slot 0 and the successive slave values in slots 1–3. A slot for a terminal that is not connected remains FFFFh after the transaction. Since FFFFh is also a valid 16-bit payload, a game must not treat that value alone as proof that a player is absent.
SIOCNT bit 7 has a role-dependent meaning: on the master it is the start bit that becomes busy during the transaction and clears when it completes; on a slave it reflects the busy state after it detects the master’s start. If the interrupt-enable bit is set, completion requests the serial interrupt. Polling code and interrupt-driven code should converge on the same completion checks rather than interpreting an interrupt as proof that the data is valid.
The communication-error flag is meaningful at the end of a transfer, not as a reliable live progress indicator. Nintendo documents errors such as a missing expected low input or a bad stop bit; the exchange can continue despite an error, and the result registers may then contain invalid data. Check the error flag and the completed multiplayer ID before delivering words to game logic. Keep “transfer finished,” “hardware reported a framing/connection error,” and “the game accepted this round” as separate states.
A safe software sequence
The following is intentionally symbolic pseudocode: actual bit masks and volatile access should come from the selected GBA SDK headers. It shows the order of ownership and checks, not a portable API or a guarantee about one game’s protocol. SD becoming high is the manual’s readiness signal that all connected terminals have entered multiplayer mode; sample SI for the master/slave role only after that signal, not from the multiplayer ID field.
/* Enter 16-bit multiplayer mode while serial control is configured. */
RCNT = sio_gpio_disabled_value;
SIOCNT = SIO_MODE_MULTI | selected_baud | optional_irq_enable;
SIOMLT_SEND = outgoing_word;
deadline_t deadline = deadline_after(link_attempt_budget);
if (!sio_wait_until_sd_terminal_high(SIOCNT, deadline)) {
abandon_link_attempt();
return;
}
/* Once SD is high, SI low selects the master; SI high selects a slave. */
if (sio_si_terminal_is_low(SIOCNT))
SIOCNT |= SIO_START; /* master initiates; slaves wait for its start */
if (!wait_for_completion_until(deadline)) {
abandon_link_attempt();
return;
}
if (SIOCNT & SIO_COMMUNICATION_ERROR)
reject_this_exchange();
else
collect_slots_and_validate_player_id();
The wait needs a deadline even when the serial interrupt is enabled. A cable can be disconnected, a device can be in another mode, or a participant can fail to answer. Do not wait forever, and do not publish partially observed result words as a completed round. Conversely, a timeout at the game’s coordination layer should not rewrite the emulated hardware’s status as though a documented hardware error had necessarily occurred.
Pace repeated transfers with a timer
Nintendo’s manual warns that GBA hardware can vary in when the completion interrupt occurs. It advises using a timer between communications and specifies an added 600-clock margin beyond the minimum send interval. The operational lesson is to schedule repeated rounds from a timer or explicit deadline, not to start the next send immediately because one test unit happened to raise its interrupt early.
For emulator validation, test one through four devices, every supported baud selection, master and slave roles, reversed or incomplete cable order, an absent endpoint, and a bad framing condition. Capture RCNT, SIOCNT, the outgoing word, each of the four result words, interrupt timing, and the post-transfer ID/error state. Compare the transfer timeline rather than only the final word values; two emulators can produce the same successful payload and still disagree about when software may safely begin the next round.
This hardware layer ends at serial words and status. It does not define a universal multiplayer packet format, lobby, trading transaction, or turn protocol. Those are game-level conventions built on top of the GBA’s ordered cable exchange. Keeping the two layers separate makes both emulator behavior and game-side recovery easier to reason about.
Related:
- Game Boy Advance DMA: Channel Priority, Trigger Timing, and Sound FIFOs
- Super Game Boy Command Protocol: Packets, Timing, and Multiplayer Input
Sources: