dolphin_read_range
Read a contiguous range of PowerPC memory as a hex dump. Efficient batch read for RAM analysis, snapshot comparison, and struct inspection.
Instructions
PURPOSE: Read a contiguous range of bytes from PowerPC memory as a hex dump. USAGE: For >4 bytes — far cheaper than looping dolphin_read8 (one bridge round-trip vs N). Max 65536 bytes/call; chunk larger reads in 64 KiB. Powers snapshot-diff RAM hunting, unknown-struct inspection, and region capture. BEHAVIOR: No side effects. The bridge reads byte-by-byte via Felk's memory.read_u8 then returns hex over the wire. No alignment requirement.
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: 'ADDR_HEX [N bytes]:' header + space-separated 2-digit uppercase hex bytes.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Starting absolute PowerPC address. Bytes [address, address+length) are read. No alignment requirement. | |
| length | Yes | Number of consecutive bytes to read (1-65536). Hard cap is the bridge's max; chunk larger reads yourself. |
Implementation Reference
- src/tools.ts:517-523 (handler)Handler for dolphin_read_range: takes address and length, calls memory.read_bytes via the Dolphin bridge, formats the result as hex bytes.
case "dolphin_read_range": { const len = p.length as number; const hex = await dol.call<string>("memory.read_bytes", [a(), len]); const bytes = hex.match(/.{2}/g) ?? []; const spaced = bytes.map((b) => b.toUpperCase()).join(" "); return ok(`${addrHex(a())} [${bytes.length} bytes]:\n${spaced}`); } - src/tools.ts:155-181 (registration)Tool registration for dolphin_read_range including inputSchema (address, length) and description.
{ name: "dolphin_read_range", description: "PURPOSE: Read a contiguous range of bytes from PowerPC memory as a hex dump. " + "USAGE: For >4 bytes — far cheaper than looping dolphin_read8 (one bridge round-trip vs N). Max 65536 bytes/call; chunk larger reads in 64 KiB. Powers snapshot-diff RAM hunting, unknown-struct inspection, and region capture. " + "BEHAVIOR: No side effects. The bridge reads byte-by-byte via Felk's memory.read_u8 then returns hex over the wire. No alignment requirement.\n\n" + GC_WII_MEMORY_MAP + "\n\n" + "RETURNS: 'ADDR_HEX [N bytes]:' header + space-separated 2-digit uppercase hex bytes.", inputSchema: { type: "object", required: ["address", "length"], properties: { address: { type: "integer", minimum: 0, description: "Starting absolute PowerPC address. Bytes [address, address+length) are read. No alignment requirement.", }, length: { type: "integer", minimum: 1, maximum: 65536, description: "Number of consecutive bytes to read (1-65536). Hard cap is the bridge's max; chunk larger reads yourself.", }, }, additionalProperties: false, }, }, - src/tools.ts:155-181 (schema)Input schema for dolphin_read_range requiring address and length (1-65536).
{ name: "dolphin_read_range", description: "PURPOSE: Read a contiguous range of bytes from PowerPC memory as a hex dump. " + "USAGE: For >4 bytes — far cheaper than looping dolphin_read8 (one bridge round-trip vs N). Max 65536 bytes/call; chunk larger reads in 64 KiB. Powers snapshot-diff RAM hunting, unknown-struct inspection, and region capture. " + "BEHAVIOR: No side effects. The bridge reads byte-by-byte via Felk's memory.read_u8 then returns hex over the wire. No alignment requirement.\n\n" + GC_WII_MEMORY_MAP + "\n\n" + "RETURNS: 'ADDR_HEX [N bytes]:' header + space-separated 2-digit uppercase hex bytes.", inputSchema: { type: "object", required: ["address", "length"], properties: { address: { type: "integer", minimum: 0, description: "Starting absolute PowerPC address. Bytes [address, address+length) are read. No alignment requirement.", }, length: { type: "integer", minimum: 1, maximum: 65536, description: "Number of consecutive bytes to read (1-65536). Hard cap is the bridge's max; chunk larger reads yourself.", }, }, additionalProperties: false, }, }, - bridge/mcp_bridge.py:77-84 (helper)Python bridge helper that performs the actual byte-by-byte memory read via Felk's memory.read_u8 and returns hex string.
def _read_bytes(p): address, length = p[0], p[1] if length < 1 or length > 65536: raise ValueError(f"length must be 1..65536, got {length}") out = bytearray(length) for i in range(length): out[i] = memory.read_u8(address + i) return out.hex()