Escaping the SGB : RTA-Friendly SNES ACE via Pokémon R/B(/Y)
Posted by: ISSOtm
Date: 2016-12-27 15:04:13
"Isn't that TAS-only ?" you might ask. Nope ! And here is how to do.
[size=14pt]Tutorial[/size]
We are first going to write a tiny payload to feed the SNES some code.
Why not using items ? Because the code maps to invalid items ! So we can't use items to store the packet data and sending code :(
And I've thought of a somewhat original (I guess) storage solution. We're gonna use Pokédex flags. Hell. Yeah.
First, setup your pack ! But don't use 8F quite yet !! The items are actually fairly simple (and cheap) to acquire, and you don't need many duplications.
8F
Any item x[any qty]
Awakening x[byte to write]
HP Up x175
Water Stone x4
Poké Ball x121
Great Ball x3
Burn Heal x3
X Accuracy x16
Antidote x34
Parlyz Heal x125
Ice Heal x46
Leaf Stone x34
TM01 x[any qty]
Lemonade x28
Guard Spec. x3
Super Repel x233
First, use 8F once. It's very important ! Then we're ready.
The setup has two modes : an "entering" mode and a "packet sending" mode.
Right now, the setup is in "entering" mode, but we will need to write a bit of code that is essential for the "packet sending" mode to function properly.
[size=18pt]BIG FAT NOTE : MAKE SURE TO NEVER USE 8F IF YOU HAVE MORE THAN 28 X ACCURACIES !!!! YOU WILL CORRUPT PARTY DATA AND MAKE 8F POTENTIALLY UNUSABLE !!!![/size]
This will also corrupt your Pokédex flags. It makes the code simpler (and actually possible), and I guess when doing SGB to SNES ACE, Pokédex progression doesn't matter that much :D
If you messed up a byte write, toss an X Accuracy and try again. This is built to be fairly forgiving :)
So, we're going to 10 bytes of code to help send packets to the SGB.
The method is the following :
[li]Toss as many Awakenings as indicated by the first number of the table[/li]
[li]Use 8F[/li]
[li]Repeat with the next number in the table.[/li]
Here goes the table :
[pre]51 | 68 | 203 | 149 | 51 | 21 | 161 | 61 | 51 | 203[/pre]
Once finished, toss all X Accuracies but one. You are now ready to write all 16 bytes of the packet to be sent.
The usage is very simple : you just need to make the quantity of Awakenings match the value you're willing to write, and then you just use 8F.
Basically, when you use 8F while having "A" Awakenings and "X" X Accuracies, the "X"th byte of the packet will turn into "A". The quantity of X Accuracies will increment each time to target the next byte to write. Full automation, man !
(If you screwed up a write, toss one X Accuracy and do it again.)
Also, don't use 8F if you have 17 X Accuracies or more ! You will screw up the code you have previously written. At best the "packet sending" mode will just not work, at worst you''l get a crash. Be cautious !
Once you have written all 16 bytes, you should swap the Lemonades with the Awakenings, the Guard Spec.s with the HP Ups, and the Super Repels with the Water Stones. The setup will be in "packet sending" mode, so use 8F, and BAM ! The packet is sent.
Then you must swap the items again to be in "entering" mode again, toss all X Accuracies but one, and repeat !
[size=14pt]Source code[/size]
Here is the code that builds the packets.
ld c, $byte
inc hl ; points to third item's quantity
xor a
ldi (hl), a ; reset it for next write
inc b
inc b
ld a, c
inc bc
inc bc
inc c
inc bc
ld l, $01
dec bc
ldi (hl), a
rrca
ld a, l
dec c
ld l, $2F
ldi (hl), a
ret
Here is the code that prepares the packet send :
ld a, $1C
scf
jr c, $D311 ; start of the second part of the packet sending payload
Here is the code appended to the packets :
; The caller made a = $1C, so we will switch to bank $1C, home of SendSGBPacket !
call BankswitchHome ; $35BC
ld l, e ; hl = $D301, start of packet
call SendSGBPacket ; $5FEB
jp BankswitchBack ; $35CD
Hex :
CD BC 35
6B
CD EB 5F
C3 CD 35
This code would have been a pain to write using items, so instead it is jumped to when using 8F in "packet sending" mode.
One last thing : I'm going to write a program that gives packet building indications to help use this setup.
It should be done in a few days.