Sword and Shield
Pokemon Sword and Shield exchange protocol-buffer messages over a publish/subscribe framework running directly on Pia.
Static readings are from a Shield 1.3.2 EUR image (01008db008c2c000, update NCA, SDK 7.7.0.0); measurements are against a French Sword 1.3.2. The two share their network code.
| page | contents |
|---|---|
| The cartridge and the session | keys, the image, Pia 4, association to the first application data |
| The sync framework | message ids, contents, holders, routing, the party payload |
| Trading | the trade screen, the box state machine, the confirmation ladder |
| Mystery Gift | the Mystery Gift menu’s local-wireless branch |
| Max Raid Battles | the den lobby, its advertisement, hosting a raid one or several consoles join, the battle a guest fights, Dynamax Adventures, leaving |
Sources
Ids, offsets and addresses come from Shield’s main or the air unless a section names a client. SYNC_ANSWERS in pokeldn/swsh/trade.py is andyjusa/nxldn-lab’s reading of a console-to-console capture (messages 97 and 60000 match pokeldn’s byte for byte). kwsch/PokePiaSWSH, lincoln-lm/swsh-lan-client, andyjusa/nxldn-lab and Slashcash/PSD speak the LAN mode from the Pia station handshake up; none covers LDN or host migration.
The field scripts
bin/script/amx/*.amx (953 in 1.3.2) are Pawn 3.x with 64-bit cells: magic 0xF1E1, version 10, flags 0x1C (compact code, sleep, no checks). Compact encoding: 7 bits per byte, high group first, sign in bit 6 of the first byte. Non-branch one-parameter opcodes are also packed as (param << 32) | op, numbered from 162 in 3.x order (LOAD.pri 162, LOAD.S.pri 164, PUSH.C 188, PUSH.S 190, STACK 191, ADD.C 197, ZERO.S 200, EQ.C.pri 201, INC.S 204, HALT 210, PUSH.ADR 212); halt 0 at offset 0 pins it.
A native is twelve bytes, u64 0 and a u32 name hash, resolved by amx_Register (0x0066d970):
h = 0; for each byte c: h = (h * 0x83) ^ c (32-bit)
Binding tables are (name, function) pairs in .data, one per module (getters such as 0x014aea00): 777 names, 512 of the 513 hashes used. Items: ItemAdd (0x014acea0), ItemSub (0x014acf40), ItemGetNum, ItemAddCheck, ItemGetCategory, GetPocketNumberFromItemNumber_. Variables: WorkGet/WorkSet (hashed 64-bit keys), TempWorkGet/TempWorkSet (indices the UI fills before the script resumes). A call is PUSH per argument, right to left, then SYSREQ.N native, bytes.
Unresolved
- Player profile: which role sample states 3 and 4 stand for in a Pokemon Camp session (
StateCreateSession,StateConnect).a_wr0301as the Crown Tundra wild area is read from the numbering only. - Battle Stadium: which save block
0x01430670reads for a stored team record, and what a save team’s descriptor holds at+0x30..+0x135before thev1/validatesignature replaces+0x36(the entry at[sp+0x28]after0x015039f0). - Sword against Shield: binary readings are Shield’s, the console is Sword; the session constants hold across the pair. Sword testing bit 0 of a card’s version mask is inferred from Shield’s code, where the test is
1 << (v == 0x2D)and eleven of the 31 call sites of0x007d4270compare against both0x2Cand0x2D, and from PKHeXRestrictVersion(1 Sword, 2 Shield, 3 both); two retail Sword snapshots carry0x2Cat MyStatus+0xA4. Sword’s own0x007d4270and its communication id literal are unread. - Mystery Gift: whether a retail console takes a kind-1 gift whose species is absent from the game as an emulated Shield does, as a bad egg named “Egg”; and what such an egg does on hatching or in a trade.