Polari

MM5 crystal skip (obsolete)

Jan 10th, 2018
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.57 KB | None | 0 0
  1. [Series of forum posts from 2015. Rewritten in https://pastebin.com/iBEUH98A and chances are you should refer to the newer version instead.]
  2.  
  3. Crystal skip is a glitch that lets you suicide on the first screen of Crystal Man's stage and respawn in the boss corridor. Skipping past the stage also causes you to miss the Beat letter, so this is only useful on a beatless route and is single biggest time save there.
  4.  
  5. First, if you aren't familiar with how the game's RAM is structured, you can find a breakdown here [no idea what this link was, probably http://tasvideos.org/GameResources/NES/Rockman/Data.html ]. Starting from 0300 you can see blocks of 18 bytes for various properties of game objects. The way these are used is that for object number X, its properties are stored in 300+X, 318+X, 330+X and so on.
  6.  
  7. The core of the glitch is in how the two-part enemies with the bouncing ball are created. Their walker part enters the screen first, and the ball on a later frame. As the ball is appearing, the game runs a subroutine that finds the first unused object slot and stores the data for the ball there, copying it from the walker. The other relevant detail is that when you die, the game fills all object slots with explosion particles. The routine that creates the ball enemy does have a check to stop the search if all slots (from 0 to 17) are filled, but what happens in this case is the code runs anyway for X=18. This causes the ball's properties to get written into the first slot of the next section, which holds Mega Man's properties.
  8.  
  9. For the most part this means that the components of the ball's X and Y positions and speeds getting mixed up and written for Mega Man, which you don't care about as you're dead. Two of the pieces are relevant though. The labels X position fraction/low/high on the previously linked page essentially mean subpixel position, pixel position, and screen number. As the enemy's pixel position gets written to Mega Man's screen number, you're sent to screen 160-something or so, which is easily enough to let you respawn in the boss corridor.
  10.  
  11. The other piece is sections labelled Variable A/B, which I assume are meant as general-purpose data storage for whatever extra things various objects might need to track. Whenever you die, the game writes 2C into 0468 and 01 into 0480 and uses these as a timer. 0468 ticks down every frame. When it reaches 00, 0480 ticks down and 0468 wraps to FF, and when both hit 00 the screen fades. This adds up to a 300-frame (5-second) wait. In crystal skip, the same routine that overwrites your current screen number with the enemy's X position after you've died, also writes the walker enemy's object index into 0480. In practice this can be either 08, 0A or 0C, which causes a 2092-, 2604- or 3116-frame wait (~35, ~43 or ~52 seconds).
  12.  
  13. As far as I can tell, the index the new enemy uses depends on how many full enemies there previously exists. When there are none, the new one gets index 08. When there's one, it gets 0A and when two, 0C. The currently used setup has the one enemy you slide into on screen and the new one that triggers the glitch uses 0A. If you do a bad setup with an extra enemy visible on the left, you'll get 0C and wait for an extra 512 frames (~8.5 seconds). If you kill a walker and leave only the ball on the screen, it seems the new enemy will use index 08, but not if the previous enemy was just killed and its explosion animation still exists. That's a potential 512-frame save if you can find a setup where you kill a walker, let it's explosion fade out, then use its the ball for the suicide and manage to get 08 into the timer instead of 0A. The timing for the glitch is very finicky though, and all such setups I've initially tried have failed to produce the glitch on any frame.
  14.  
  15. As the glitch only causes limited object data corruption, I don't see a way to alter it to produce any other useful effects, and the aforementioned frame save is the only improvement I can imagine. Also the subroutine that causes the glitch is specific to the one type of enemy involved, which doesn't appear in any other stage in the game, so while the same bug might exist in other code, this specific piece can't be utilized anywhere else.
  16.  
  17. ---
  18.  
  19. Previously I was really sloppy with examining the object indices used and turns out the game doesn't actually arrange the enemies into the first slots, but instead works as you would expect, never moving them around after they are created. As new enemies are always created in the first free slots, it's easy to manipulate which one the enemy used for the glitch ends up in, by keeping track of which slots the previous enemies are using and killing them as needed. It seems there's some kind of a quirk here that prevents the glitch from happening if the new enemy uses the slot 08, as even with the known working setup for the suicide I am completely failing to find any frames where the new enemy won't either remain fully offscreen or appear fully spawned.
  20.  
  21. On the other hand, the value 09 does work. One way to set this up is to kill the first enemy's bottom part (stored in index 08) and have its ball (stored in index 09) on screen as the third enemy (the one you're suiciding into) spawns. At this point you have the ball in 09, the second enemy in 0A and 0B, and the third one will get 08 for its bottom part and 0C for its ball. Now as you let the ball and the second enemy go off screen, you're left with the third one using 08 and 0C, and the fourth one getting 09 for its bottom part, as we wanted to. Another possibility is to kill the first enemy completely before the second one spawns, so the second one ends up in 08 and 09, then use its ball in the same way.
  22.  
  23. Here's practical instructions for one possible way to do this:
  24. 1) Use the first enemy for damage while letting the second one spawn and shoot it once
  25. 2) Right after the seventh hit, shoot it again
  26. 3) Immediately start sliding right and take two more hits from the ball
  27. 4) Wait one walk cycle of the third enemy to let the ball disappear
  28. 5) Execute the glitch
  29.  
  30. Compared to my old setup, this version saves 256 frames on the death timer, but loses about 50 to more waiting between the last damage and the suicide. Another straightforward setup that looked promising was to kill the first enemy right before you take the fifth hit, slide along the ball taking damage from it, then take the second to last hit from the third enemy so that the knockback puts you into the correct position for the slide. This has very little downtime between hits, but for some reason the glitch itself just isn't there, again.
  31.  
  32. Given how much leeway you have in setting this up, it seems very likely that a better working setup does exist and is just waiting to be found. I doubt I'll put too much effort into finding it though before I get back to playing this game.
  33.  
  34. ---
  35.  
  36. Turns out I had a major oversight in analysing the subroutine that returns the broken index. The seemingly irrelevant instructions to set the processor carry flag before returning actually work as an error code, and most instances that call that subroutine are followed by a Branch if Carry Set instruction. There are six instances where the subroutine call (20 6F F1) appears in PRG ROM without it being followed by the BCS instruction (B0). These are called, in the order they appear in the ROM, when Q9 spawns, when the platforms in the Q9 fight spawn, when Wily Press spawns, when Darkman spawns, when Wily Capsule is killed, and when those enemies in Crystal Man stage spawn. All except for the crystal stage enemy appear at the end of a stage, so there's nothing to be gained from moving yourself to another room in those cases.
Add Comment
Please, Sign In to add comment