Spacetime Beam

From A complete guide to Super Metroid speedrunning
Jump to: navigation, search

The Spacetime Beam is the result of an invalid beam selection that occurs when all beams except Wave Beam are selected. It can function without Charge Beam, but it is recommended that it also be equipped for easier utilization.

Spacetime Reset

Original description from Metroid 2002:

This glitch causes everything in the game except your current equipment to reset to its original state. This means that all items and bosses will be back to collect/kill again, and all doors that did not start out blue will revert to their original state.

To perform it, you must equip the space/time beam, which is smilar to the Murder Beam, except it is an uncharged shot and the wave beam is not equipped, fire once, then leave the room you are in. It cannot be done in every room, as the room must be fairly large, and even then it still doesn't work in some rooms. The above video shows one possible location.

If, after preforming the glitch, you save and quit the game, when you next play, you will rewatch the game's opening sequence, then restart at Ceres Station with all equipment intact except for missiles, which vanish because during the flashback to the Mother Brain fight, the game gives Samus four missiles to use, then takes them away again.

Wrong Warps

The Spacetime Beam can also be used to alter the state of the room such that Samus can touch a transition block that will take her elsewhere on Zebes. There are several known warps that are possible, three of which are currently used in Any% GT Code, and several others that were used in older routes of the category.

How It Works

The following is what is known so far about how it works on a technical level:

At 0090:AEDD, there is the following instruction:

$90/AEDD FC 68 0C    JSR ($0C68,x)[$90:AD16] A:912F X:0000 Y:0038 P:eNvmxdizc

This is an "absolute indexed indirect" jump that reads the address at $0C68 + X and jumps to it. $0C68 contains different values depending on what beam is shot, so this code calls different routines depending on what is fired. In the case of this beam, $0C68 contains AD16, so the code then jumps to 0090:AD16.

At that memory location, the following subroutine exists:

$90/ACFC 29 FF 0F    AND #$0FFF              
$90/ACFF 0A          ASL A                   
$90/AD00 A8          TAY                     
$90/AD01 A9 90 00    LDA #$0090              
$90/AD04 EB          XBA                     
$90/AD05 85 01       STA $01    [$00:0001]   
$90/AD07 B9 C9 C3    LDA $C3C9, y
$90/AD0A 85 00       STA $00    [$00:0000]   
$90/AD0C A0 00 00    LDY #$0000              
$90/AD0F A2 00 00    LDX #$0000              
$90/AD12 B7 00       LDA [$00], y
$90/AD14 9F C0 C1 7E STA $7EC1C0, x
$90/AD18 E8          INX                     
$90/AD19 E8          INX                     
$90/AD1A C8          INY                     
$90/AD1B C8          INY                     
$90/AD1C C0 20 00    CPY #$0020              
$90/AD1F 30 F1       BMI $F1    [$AD12]      
$90/AD21 60          RTS

When run as intended, this code will read 16 bytes starting at the address that gets written to $00 and $01 in RAM and then write it back to RAM at $7EC1C0. It does this by increasing the Y register twice for every time it loops and compares it to $20, and as long as Y - $20 is negative, it will continue the loop; however, with this beam, the jump into this instructions occurs right into the middle of the STA instruction at $90/AD14.

This effectively converts that operation into the following:

$90/AD16 C1 7E       CMP ($7E,x)

This effectively does nothing in this case, and the code moves on to INX at $90/AD18.

The one big thing to note here is that this completely bypasses the setup for this loop where registers X and Y get cleared to zero and where $00 and $01 are setup with the source address, and this is what causes the effects of the beam. In this case, X seems to be set to zero, so that means writes will start at $7EC1C0 as intended; however, Y retains the value from whatever it was set to by any previous code that used it.

As a result, when Y contains a huge negative value, the loop will run all the way up until Y gets back to being $20 or above. This causes an overflow to happen where a huge part of RAM after $7EC1C0 gets overwritten. The data that is written is read from ((the address at $00-$02) + Y), and the values in $00-$02 seems to at least be different depending on room, so that also changes which data gets copied along with the fact that the value of Y decides from where the copying will start. Since the value of Y is used from whatever code was run previously, this is what causes different data when shooting different beams, Missiles, Super Missiles, et cetera, since the code to update these beams will leave the Y register at different values.

This is pretty much all I know so far, and some of it might be incorrect. I'll try to update it as I learn more. If there are any questions, feel free to contact me on IRC.

- total

See also

External links