ACE RTA — the four-spawn finish, using X as well as Y ===================================================== A Link to the Past (SNES, 1991), JP 1.0, measured on Mesen. What is new: the X byte ----------------------- In the old method a spawn placed one chosen byte. A spawn that misslots into slot 80+i writes its Y position (the low byte) into $0C4A+i, the ID of front slot i. That is why Link's Y had to be exact at every spin. The same misslot also writes the spawn's X position (the low byte) into $0C54+i. The disassembly calls that byte MISCN, a scratch byte each kind of ancilla uses for its own bookkeeping. The game never reads MISCN to decide which routine to run, so any value can sit there without consequences, including $60, which is RTS. So one spawn places two chosen bytes, not one, and Link's X matters as much as his Y. Everything below follows from that. The sequence ------------ slot ID ($0C4A+i) MISCN ($0C54+i) 0 69 3A 1 0E 85 2 10 10 3 06 60 Four spawns instead of seven, and the RTS is a MISCN byte, so no bomb. The instructions are the ones the old sequence ran: ADC #$0E, DEC A, STA $10, return. What changed is where they sit. Only the first two bytes stay in the ID array. Then a branch (10 06) jumps six bytes forward, out of the ID array and into the MISCN array, where the other three instructions are. Each spawn fills one byte of each array. The byte choices are tighter than they look: * $0E is the only ID that both survives in its slot and gets A near $19. $0D would land on $19 exactly and save the DEC, but an ancilla with ID $0D deletes itself in about six frames. * The branch has to be $10 or $90. Both are the same ancilla, so both survive, and since the ADC leaves the carry clear, BCC ($90) branches just like BPL ($10). Every other branch opcode is an ID that crashes or deletes itself. * The branch distance has to land on a MISCN byte a spawn can write, and $06 is the only value that does: six bytes past the next instruction at $0C4E is $0C54, the start of the MISCN array. The deadline ------------ ID $06 is the wall-hit spark. Its routine adds 1 to the slot's byte at $0C5E+i every second frame and deletes the ancilla when that byte reaches $05. The misslot fills $0C5E+i with the spawn's Y high byte. With Link in the $05xx band the byte starts at $05 and has to go all the way round, 256 steps, about 512 frames, before it is $05 again. In the $04xx band it starts at $04, and the first step kills it. So from the moment slot 3 gets its $06, there are about 510 frames to reach the entry, the frame on which the $69 in slot 0 is dispatched and the bytes run. Measured in a real run: the entry still works 509 frames after the write and fails at 513. Filling the front slots ----------------------- As before, every spin needs slots 0-4 full when its spark looks for a slot, or it takes a free front slot instead of going through the search. The old method's two bombs in slots 1 and 0 are out (why is below), and only two things in the route's inventory can hold a front slot: * A Somaria block. It lands in the highest empty slot of 4..0, never times out, and only one can exist: pressing Y with a block out pops it instead of placing another. * A pop. It frees the block's slot and spawns four bullets, in the order right, left, down, up. With k free front slots, the first k bullets take them and the other 4-k go through the search, each using up a match (the next misslot down the list). After the first spin, slot 3 holds $06 for good, and slot 4 already holds the $10 that step 4 of the setup left there. So every later pop has at most three free front slots, and at least its up bullet goes through the search. That is the problem and the answer in one: aim the up bullet so that the byte it writes is the byte you wanted anyway. Slot 2's pair comes from a bullet, and only three spins are needed: # action Link Y, X, facing writes 1 block, pop, spin fires 13 frames after the pop $050E, $0559 down slot 3 06 / 60 2 block placed facing up $0427, $0510 up (takes slot 2) 3 pop $0416, $057E down slot 2 10 / 10 4 that pop's spin, 13 frames later $0416, $057E down slot 1 0E / 85 5 block placed while charging $0449, $0530 up (takes slot 0) 6 spin, 13 frames after that press $0449, $0530 up slot 0 69 / 3A 24 magic, no bombs. A block is also the only safe thing to put in slot 0. Our own $0E and $10 in slots 1 and 2 arm the Ancilla33 wipe: if slot 0's $0C5E byte ever reads $06 while they are there, the IDs of slots 0 and 1 are zeroed within a frame. A block's $0C5E byte is zeroed at spawn and never counts up, so it cannot get there. A bomb's does, on tick 182. Bombs are out for a second reason. With Somaria on Y, reaching them means the item menu, and the menu does not pause the ancillae. The $06 counter took 91 steps during 182 frames of open menu, the same rate as in play, and a trip to bombs and back costs about 229 frames of the window. Charge sparks sit unchanged through a menu, which makes it look frozen. It is not. The bytes, and what the CPU does with them ------------------------------------------ $0C4A: 69 0E 10 06 IDs of slots 0-3 $0C54: 3A 85 10 60 MISCN of the same slots As before, slot 0's $69 sends the dispatcher through the operand of an unrelated CMP $0C4A,Y and into $08:0C4A, and the ID array runs as code: $0C4A 69 0E ADC #$0E A = $0C + $0E = $1A, N = 0, C = 0 $0C4C 10 06 BPL $0C54 jumps out of the ID array... $0C54 3A DEC A ...and into the MISCN array: A = $19 $0C55 85 10 STA $10 game mode := $19 $0C57 60 RTS back into HandleAllAncilla A is $0C when the code starts, which is why the number added is $0E: $0C + $0E = $1A, one above the mode we want, and DEC A brings it to $19. The RTS matters as much as the rest. Without it the CPU keeps reading memory as code and the game crashes instead of winning. The two arrays interlock. The four ID bytes are all Y positions and the four MISCN bytes are all X positions: Link's, plus the spark's offset for his facing, or the bullet's own. $0C4A = $69 ADC opcode $0449 + 32 (spark offset facing up) $0C4B = $0E its operand $0416 - 8 (facing down) $0C4C = $10 BPL opcode the bullet $0C4D = $06 its operand $050E - 8 (facing down) $0C54 = $3A DEC A $0530 + 10 (facing up) $0C55 = $85 STA opcode $057E + 7 (facing down) $0C56 = $10 its operand the bullet ($10 = the game mode byte) $0C57 = $60 RTS $0559 + 7 (facing down) Measured trace on the entry frame: 08:0C4A 69 → 08:0C4C 10 → 08:0C54 3A → 08:0C55 85 → 08:0C57 60 then mode $19. Module19 zeroes slots 0-5 on its first frame, so it can only run once.