I wrote these notes right as the stream ended so we could capture the knowledge we gained after streaming for 2-3 hours. I'm hoping to revisit these myself and get to the bottom of things, but we'll see if time permits. In the meantime, a lot of other people in the stream found watching the process helpful. If anyone else wants to keep poking at this and moving forward, go for it! Hopefully, these notes will help.
- The ROM: Super Mario Bros. 3 (U) (PRG1) [!].nes
- The Debugger: FCEUX 2.2.2 (for Windows, which has debugging capability)
- The Lua Script: http://acbit.net/static/tas/dpcmglitch.lua
- The Inputs: http://acbit.net/static/tas/inputs
I used File -> Lua -> New Lua Script Window
to load the lua script (which loads the inputs) in FCEUX. Then, I
opened Debug -> Debugger...
and Debug -> Trace Logger...
. I turned on "Symbolic Trace" in the "Trace Logger" so
I could see where I came from when I hit one of my breakpoints.
I set execute breakpoints on:
- $0000-$00FF - Scratch
- $0100-$01FF - Stack
At this point, doing NES -> Reset
in the main window and Run
in the debugger while having logging started got me
to most of what's in the notes section below.
Question:
We know that the function at $FEBE can be placed into an infinite loop by never having two values from $FF12 match when coming through the loop. How does that lead us to hitting the credits sequence..?
See http://arstechnica.com/gaming/2016/07/how-to-beat-super-mario-bros-3-in-less-than-a-second/ for more info.
Starting to answer:
These instructions appear to place an unexpected value onto the stack (FIXME: why?):
0F:F7B0:AD FF 7A LDA $7AFF = #$00
>0F:F7B3:48 PHA
This instruction then leads us to executing on the stack (FIXME: not entirely sure why yet):
A:FF X:07 Y:01 S:E4 P:NvUbdIzc $A84B:60 RTS ----
When we start executing on the stack, we go to $0101, which decodes as a jump:
> :0101:20 00 00 JSR $0000
This transfers execution to the beginning of memory:
> :0000:A8 TAY
We service some interrupts (FIXME: one interrupt?) and then start executing at $0001 again:
> :0001:9A TXS
We stumble through more interrupts (FIXME: how many?) as we're executing through the beginning of the address space. Then, we hit the following instruction:
> :00F5:50 98 BVC $008F
This transfers our execution backward on the scratch space to more BRK
s that we're going to slide through.
Then, this random instruction appears and we no longer execute anything further in this address space:
> :00F6:20 5A B8 JSR $B85A
Credits roll and everything is great! ...why? (FIXME: It's 3am...figure this out later :P)