I'm experimenting with making a total control hack using as little time to set up as possible. Noting that it is possible to switch 11-byte blocks (thanks p4wn3r), I've been planning to inject the following byte sequence into D358:
00 21 FF D3 AF 4F 7C F3 E2 F2 BA 28 F9 5F CB 37 AA 32 53 20 F1 58 D3
Notice that this sequence is 23 bytes long, and D359 is the start of an 11-byte block.
The byte sequence has to be carefully chosen since not all items are tossable (and some of them crash when selected). I also want the program to be zero-free, except for D358.
Explanation:
00 NOP (item hack)
21 FF D3 LD HL D3FF
AF XOR A (A:=0)
4F LD C A (C:=A)
input:
7C LD A H (A:=H, works because D3 has bit 4 on and bit 5 off)
F3 DI (disable interrupts)
E2 LDH (C) A ((FF00):=A)
F2 LDH A (C) (A:=(FF00))
BA CP D (check input changed)
28 F9 JR Z input (if not, goto input)
5F LD E A (E:=A)
CB 37 SWAP A (swap nibbles)
AA XOR D (XOR with last input)
32 LDD (HL), A (write A to memory pointed by HL and decrement HL)
53 LD D E (D:=E, new last input)
20 F1 JR NZ input (goto input; NZ is for item hack)
58 D3 (not executed) (this pointer falls on D36D and jumps to D358)
This program starts writing from D3FF backwards. It writes a "nibble chain program" in which the low nibble of byte N is the same as the high nibble of byte N+1. Also, the nibbles of a byte cannot be the same. Input is A, B, Select, Start which can write any nibble values from 0x0 to 0xF. The program is set up so that when writing backwards, it will trample D36C (the F1 in "20 F1", or JR NZ input) which would allow jumping to the new program. I still have to check that a valid program can be written but I am confident that it can be done.
I made a movie (starting from savestate) showing how the 23 bytes above can be injected into D358 (actually, I made a mistake and used D4 instead of D3 in "21 FF D3", or LD HL D3FF). This is how (after reset and continue):
- Switch the 6th and 10th pokemon to overwrite the item counter.
- Throw away the 3rd item; this messes up all the game settings and causes text to appear instantly.
- Switch the 9th and 11th pokemon; this fills the item area with FF, which is much faster to scroll through (this is why I aim for a zero-free program, since it is not possible to get 0 if the item quantity is 0xFF).
- Toss items so that half the bytes of D322-D337 are set to the program above (excluding initial NOP).
- Switch the 17th and 18th pokemon; this switches D322-D32C with D32D-D337 to switch item parity.
- Toss items to complete D322-D32C and D32D-D337 (these are still switched).
- Switch the 17th and 19th pokemon; this sends D322-D32C to D338-D342 so D32D-D342 contains the program (except for the initial NOP) in the correct order.
- Switch the 16th and 17th pokemon; since D321 is 0, this sends D317-D321 to D322-D32C so D32C becomes 0, so D32C-D342 contains the above program.
- Finally, switch the 11th and 12th pokemon; this sends D32C-D342 to D358-D36E.
- Close the menu.
Since most of the time is spent scrolling through numbers, it may be possible to optimize further by having a program that may be longer but has numbers closer to 0xFF and 0x00. Numbers close to 0x80 take the longest.