Here:
2140 rwb++++ APUIO0 - APU I/O register 0
2141 rwb++++ APUIO1 - APU I/O register 1
2142 rwb++++ APUIO2 - APU I/O register 2
2143 rwb++++ APUIO3 - APU I/O register 3
xxxxxxxx
These registers are used in communication with the SPC700. Note that
the value written here is not the value read back. Rather, the value
written shows up in the SPC700's registers $f4-7, and the values
written to those registers by the SPC700 are what you read here.
If the SPC700 writes the register during a read, the value read will
be the logical OR of the old and new values. The exact cycles during
which the 'read' actually occurs is not known, although a good guess
would be some portion of the final 3 master cycles of the 6-cycle
memory access.
Note that these registers are mirrored throughout the range
$2140-$217f.
Anomie also has an
SPC700 doc. This part in particular seems to be useful:
To properly manipulate this into uploading your data, the following procedure
seems to work:
1. Wait for a 16-bit read on $2140-1 to return $BBAA.
2. Write the target address to $2142-3.
3. Write non-zero to $2141.
4. Write $CC to $2140.
5. Wait until reading $2140 returns $CC.
6. Set your first byte to $2141.
7. Set your byte index ($00 for the first byte) to $2140.
8. Wait for $2140 to echo your byte index.
9. Go back to step 6 with your next byte and ++index until you're done.
10. If you want to write another block, write the next address to $2142-3,
non-zero to $2141, and index+2 (or +3 if that would be zero, otherwise
it'll screw up the next transfer) to $2140 and wait for the echo. Then go
to step 6 with index=0.
11. Otherwise, you can jump to some code you've just uploaded. Put the target
address in $2142-3, $00 in $2141, and index+2 in $2140 and wait for the
echo. Shortly afterwards, your code will be executing.
So you'll want to set a read breakpoint for $2140. The game will check for when the value it loads from that register equals $BBAA, and when that happens, it'll begin the SPC load process as described. You don't need to understand it so much as recognize when it's taking place: you won't be modifying this code, you'll be modifying the code that ultimately
calls this code.