Difference between revisions of "Subpixels"

From ALttP Speedrunning Wiki
Jump to: navigation, search
Line 1: Line 1:
This game uses subpixels for its movement. This is how Link gets the movement speed of 2-1-2-1 on normal ground etc. This mechanic is not fully understood yet, so there might be some errors on this page.
+
This game uses subpixels for its movement. This is how Link gets the movement speed of 2-1-2-1 on normal ground etc.
  
If you want to help figure this out, you can memory watch 7E002A and 7E002B in your emulator (might be 002A and 002B in some emulators). Those are the Y and X subpixels.
+
== How the coordinate and subpixel is updated during movement ==
  
== How subpixels are set ==
+
* Link has a static velocity when moving around.
 +
** Walking, normal ground: $18
 +
** Dashing, normal ground: $40
 +
** Diagonal, normal ground: $10
 +
** Walking, stairs: $0B
 +
** Dashing, stairs: $0A
 +
** Diagonal, stairs: $0B
 +
** Walking, shallow water: $14
 +
** Dashing, shallow water: $30
 +
** Diagonal, shallow water: $0D
 +
* When walking leftwards or upwards, the speed is
 +
* The first significant digit (1 in the case of walking on normal ground) is added to the coordinate directly, no matter what.
 +
* The least significant digit (8 in the case of walking on normal ground) is added first to the subpixel coordinate. If this causes the subpixel coordinate to overflow/wrap, we add an additional pixel to the coordinate.
 +
* The game will reset Link's subpixel accumulator whenever you change direction of movement. A movement after a standstill counts as changing the direction of movement.
 +
** Note that if you're walking ^, it will reset the subpixel accumulator both when you go to ^> and when you go back to ^ again.
 +
:: This means that pumping into a wall will function as two pumps, both when you press and when you release the extra dpad button.
 +
* Starting/executing a dash will not reset the subpixel accumulator. But if you cancel the dash with a movement, it will be reset.
 +
** If you however start a dash that ends up transitioning to another screen, the subpixel accumulator is not reset unless you start moving in a different direction on the next screen.
  
* When moving in one direction, the subpixel is incremented or decremented depending on the surface Link is moving on, and which direction he is moving.
+
'''Example: Walking on ground (movement speed is 18), downwards'''
* Walking upwards or leftwards ''increments'' the corresponding X/Y subpixel, walking downwards or rightwards ''decrements'' the corresponding X/Y subpixel.
+
* frame 1: Subpixel = 0x00 + 0x80 = 0x80. Coordinate = 0 + 1 = 1
* The only way to "start over" (reset) the subpixel value, is by changing direction of movement. A movement after a standstill counts as changing the direction of movement.
+
* frame 2: Subpixel = 0x80 + 0x80 = 0x00. Coordinate = 1 + 1 + 1 = 3  (subpixel overflow).
* Starting/executing a dash will not move the subpixels at all. But canceling a dash with a movement (holding another direction for 2f or more) will count as normal movement from a standstill.
+
* frame 3: Subpixel = 0x00 + 0x80 = 0x80. Coordinate = 3 + 1 = 4
* If you start a dash with a certain subpixel, then transition and hold the dpad to move forward on the next screen, the subpixel is not reset - you continue where you left off before you started the dash.
+
* frame 4: Subpixel = 0x80 + 0x80 = 0x00. Coordinate = 4 + 1 + 1 = 6  (subpixel overflow).
 
+
* Etc
== Explanation on why the movement works as it does ==
 
 
 
This is not really verified in any other way than it fits what we can see when frame advancing while looking at the coordinate and subpixels.
 
 
 
* When the subpixel wraps, your movement speed gets a -1.  
 
* On normal ground, the default movement speed is 2.
 
* On stairs, the default movement speed is 1.
 
  
 
'''Example: Walking on ground (movement speed is 2), upwards'''
 
'''Example: Walking on ground (movement speed is 2), upwards'''
* frame 1: Subpixel = 0x00 + 0x80 = 0x80. Doesn't wrap, so you get 2.
+
* frame 1: Subpixel = 0x00 - 0x80 = 0x80. Coordinate = 0 + 1 + 1 = 2 (subpixel overflow)
* frame 2: Subpixel = 0x80 + 0x80 = 0x00. Wraps, so you get 2 - 1 = 1.
+
* frame 2: Subpixel = 0x80 - 0x80 = 0x00. Coordinate = 2 + 1 = 3
* Repeats
+
* Etc
 
 
'''Example: Walking on ground (movement speed is 2), downwards'''
 
* frame 1: Subpixel = 0x00 - 0x80 = 0x80. Wraps, so you get 1.
 
* frame 2: Subpixel = 0x80 - 0x80 = 0x00. Doesn't wrap, so you get 2.
 
* Repeats
 
  
 
'''Example: Walking on stairs (movement speed is 1), upwards'''
 
'''Example: Walking on stairs (movement speed is 1), upwards'''

Revision as of 14:31, 12 January 2018

This game uses subpixels for its movement. This is how Link gets the movement speed of 2-1-2-1 on normal ground etc.

How the coordinate and subpixel is updated during movement

  • Link has a static velocity when moving around.
    • Walking, normal ground: $18
    • Dashing, normal ground: $40
    • Diagonal, normal ground: $10
    • Walking, stairs: $0B
    • Dashing, stairs: $0A
    • Diagonal, stairs: $0B
    • Walking, shallow water: $14
    • Dashing, shallow water: $30
    • Diagonal, shallow water: $0D
  • When walking leftwards or upwards, the speed is
  • The first significant digit (1 in the case of walking on normal ground) is added to the coordinate directly, no matter what.
  • The least significant digit (8 in the case of walking on normal ground) is added first to the subpixel coordinate. If this causes the subpixel coordinate to overflow/wrap, we add an additional pixel to the coordinate.
  • The game will reset Link's subpixel accumulator whenever you change direction of movement. A movement after a standstill counts as changing the direction of movement.
    • Note that if you're walking ^, it will reset the subpixel accumulator both when you go to ^> and when you go back to ^ again.
This means that pumping into a wall will function as two pumps, both when you press and when you release the extra dpad button.
  • Starting/executing a dash will not reset the subpixel accumulator. But if you cancel the dash with a movement, it will be reset.
    • If you however start a dash that ends up transitioning to another screen, the subpixel accumulator is not reset unless you start moving in a different direction on the next screen.

Example: Walking on ground (movement speed is 18), downwards

  • frame 1: Subpixel = 0x00 + 0x80 = 0x80. Coordinate = 0 + 1 = 1
  • frame 2: Subpixel = 0x80 + 0x80 = 0x00. Coordinate = 1 + 1 + 1 = 3 (subpixel overflow).
  • frame 3: Subpixel = 0x00 + 0x80 = 0x80. Coordinate = 3 + 1 = 4
  • frame 4: Subpixel = 0x80 + 0x80 = 0x00. Coordinate = 4 + 1 + 1 = 6 (subpixel overflow).
  • Etc

Example: Walking on ground (movement speed is 2), upwards

  • frame 1: Subpixel = 0x00 - 0x80 = 0x80. Coordinate = 0 + 1 + 1 = 2 (subpixel overflow)
  • frame 2: Subpixel = 0x80 - 0x80 = 0x00. Coordinate = 2 + 1 = 3
  • Etc

Example: Walking on stairs (movement speed is 1), upwards

  • frame 1: Subpixel = 0x00 + 0x50 = 0x50. Doesn't wrap, so you get 1.
  • frame 2: Subpixel = 0x50 + 0x50 = 0xA0. Doesn't wrap, so you get 1.
  • frame 3: Subpixel = 0xA0 + 0x50 = 0xF0. Doesn't wrap, so you get 1.
  • frame 4: Subpixel = 0xF0 + 0x50 = 0x40. Wraps, so you get 1 - 1 = 0.

Example: Walking on stairs (movement speed is 1), downwards

  • frame 1: Subpixel = 0x00 - 0x50 = 0xB0. Wraps, so you get 1 - 1 = 0.
  • frame 2: Subpixel = 0xB0 - 0x50 = 0x60. Doesn't wrap, so you get 1.
  • frame 3: Subpixel = 0x60 - 0x50 = 0x10. Doesn't wrap, so you get 1.
  • frame 4: Subpixel = 0x10 - 0x50 = 0xC0. Wraps, so you get 1 - 1 = 0.

Basically it works like an "anti subpixel".

How it affects slope dashes

Dashing on a slope is a fairly volatile thing when you frame advance through it. Link will move anything from 0 to 3 pixels in both the horizontal or vertical direction, seemingly at random. We're not sure the exact rules, but it looks like different parts of the slope will give different pixel boosts.

Another factor is subpixels. Depending on what subpixel you have, you might or might not get an extra pixel boost at any point during the slope dash. This means that even if you start your dash from the exact same coordinate, the slopedash can go fast or slow depending on the subpixel value.

One way to make sure you get the same subpixel is to hit diagonal before starting the dash.

Bomb Clips

Since a criteria for performing a Bomb Clip is that you are positioned exactly below the explosion, your subpixel value will matter just as much as your coordinate, since different paths through the slope might or might not include the coordinate where Link is directly below.

Some setups works the same for both subpixel=0x00 and subpixel=0x80, in which case it doesn't matter.

If a setup requires a specific subpixel, you would need to go from a standstill to a movement for an exact amount of frames, before starting the dash (for example hit > + A on the same frame).