dolphin_write32
Write a 32-bit big-endian value to PowerPC memory at a specified absolute address. Used for modifying game state and cheats in GameCube/Wii games.
Instructions
PURPOSE: Write an unsigned 32-bit big-endian value to PowerPC memory at the given absolute address. USAGE: The workhorse for cheats — most game state is 32-bit. For 8/16-bit values use dolphin_write8/write16; for true 64-bit fields use dolphin_write64 (atomic, vs two non-atomic write32s). For floats, reinterpret the IEEE-754 bits as an integer first. BEHAVIOR: DESTRUCTIVE: overwrites four bytes with no undo. Address MUST be 4-byte aligned. Writes to read-only regions are silently dropped.
GameCube + Wii main address space landmarks (PowerPC, big-endian): 0x80000000-0x817FFFFF MEM1 main RAM (24 MiB) — GameCube + Wii game code & data GameCube games stay entirely within MEM1. Wii games use MEM1 for code and frequently-accessed data. 0x80000020 OS_GLOBALS — game-info struct (disc ID, FST, etc.) 0x80000034 OS_ARENA_LO (start of free MEM1 heap) 0x80003100 OS_REPORT (developer-console mirror, varies by SDK) 0x90000000-0x93FFFFFF MEM2 (64 MiB) — Wii ONLY. Larger texture/asset data, IOS work areas. Reading MEM2 on a GameCube game returns garbage / FAIL. 0xCC000000-0xCC00FFFF Hollywood I/O (Wii) / Flipper I/O (GameCube) — DMA, GPU FIFO, AI, EXI registers. Reads are usually safe, writes can wedge the emulator. Avoid. 0xCD000000-0xCD007FFF Wii-only Hollywood registers.
Notes: • All multi-byte values are BIG-ENDIAN on the real hardware. Felk's memory.read_u*/write_u* helpers handle the byte swap for you — the value you see is the value the game sees as a u32. • Addresses are 32-bit; Felk truncates the high bits of any u64 address argument. • Pointers in MEM1 are often stored as 4-byte addresses with the high bit set (e.g. 0x81234567). Dereferencing them requires no masking — pass the raw value back into memory.read_*.
RETURNS: 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX'.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Absolute PowerPC virtual address (0x80000000-0x9FFFFFFF). Pass as a number; hex literals like 0x80001000 are fine. Reads 4 consecutive bytes starting here and interprets them as a big-endian value. MUST be 4-byte aligned (address % 4 === 0). PowerPC raises an alignment exception on misaligned access in hardware, but Dolphin's emulated bus is forgiving and silently returns the aligned-down word — i.e. you get the bytes from address & ~3, not what you asked for. For unaligned multi-byte reads use dolphin_read_range and assemble client-side. Useful ranges: 0x80000000-0x817FFFFF for MEM1 (GC + Wii), 0x90000000-0x93FFFFFF for MEM2 (Wii only). | |
| value | Yes | 32-bit value (0-4294967295 / 0x00000000-0xFFFFFFFF). For signed, encode as two's complement. For floats, reinterpret the IEEE-754 bits as an integer first. |
Implementation Reference
- src/tools.ts:227-248 (schema)Tool definition (name, description, inputSchema) for dolphin_write32 — declares the tool with address (integer, 4-byte aligned) and value (unsigned 32-bit integer 0-4294967295).
name: "dolphin_write32", description: "PURPOSE: Write an unsigned 32-bit big-endian value to PowerPC memory at the given absolute address. " + "USAGE: The workhorse for cheats — most game state is 32-bit. For 8/16-bit values use dolphin_write8/write16; for true 64-bit fields use dolphin_write64 (atomic, vs two non-atomic write32s). For floats, reinterpret the IEEE-754 bits as an integer first. " + "BEHAVIOR: DESTRUCTIVE: overwrites four bytes with no undo. Address MUST be 4-byte aligned. Writes to read-only regions are silently dropped.\n\n" + GC_WII_MEMORY_MAP + "\n\n" + "RETURNS: 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX'.", inputSchema: { type: "object", required: ["address", "value"], properties: { address: { type: "integer", minimum: 0, description: addrParamDesc(4) }, value: { type: "integer", minimum: 0, maximum: 4294967295, description: "32-bit value (0-4294967295 / 0x00000000-0xFFFFFFFF). For signed, encode as two's complement. For floats, reinterpret the IEEE-754 bits as an integer first.", }, }, additionalProperties: false, }, }, - src/tools.ts:533-536 (handler)Handler for dolphin_write32 — calls Dolphin bridge method 'memory.write_u32' with the address and value, returns success message with formatted hex.
case "dolphin_write32": { await dol.call("memory.write_u32", [a(), p.value as number]); return ok(`Wrote ${fmtHex(p.value as number)} → ${addrHex(a())}`); } - src/tools.ts:488-489 (registration)Tool registration — registerTools() sets up ListToolsRequestSchema handler that exposes TOOLS array (which includes dolphin_write32) and CallToolRequestSchema handler that dispatches to the switch case.
export function registerTools(server: Server, dol: DolphinClient): void { server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS })); - bridge/mcp_bridge.py:88-88 (helper)Python bridge handler for memory.write_u32 — calls Felk's memory.write_u32(address, value) on the emulator side, returns None.
def _write_u32(p): memory.write_u32(p[0], p[1]); return None - bridge/mcp_bridge.py:143-143 (registration)Route mapping in the bridge dispatch table — maps the string 'memory.write_u32' to the _write_u32 function.
"memory.write_u32": _write_u32,