Hi there!
I've been working on a Megaman fangame project on Unity, and for a couple of days now, I've been trying to find out how his jump curve operates on Megaman 5 with no success.
Has anyone here already done this, and would help me out with this info?
I'm figuring everything out by Memory Watching on FCEUX and using NES roms.
The variables I'm currently looking at are:
0360-0377 Y position fraction (that is, Y sub-pixel position (?) )
0378-038F Y position low
0390-03A7 Y position high
03D8-03EF Y speed low
03F0-0407 Y speed high
Here's what I managed to find out:
The gravity is 064.
The Positon Fraction and Y Speed Low Byte increments operate between 0 and 255 (this is actually true for every other delta in the game).
His speed starts at 4.192 pixels, and will decrease by .064 (gravity value) every frame.
If I correctly understood this, whenever his Position Fraction is .192, the ACTUAL distance his sprite moves will drop by 1 pixel. Also, there seems to be some sort of rounding up (For he actually moves 5 pixels when his speed is 4.192, 4 pixels when his speed is 3.128 etc.).
The position fraction actually forms a pattern:
0 64 192 128 128 192 64 0
Problem is, nor the rounding up nor the Position Fraction increments seem to make any sense to me.
What am I missing here? How are these increments and rounding ups being done?
I guess you could say I could just make an approximation and use my own method, and that's OK, but what I'm facing here is a question of honor
It's though seeing something that doesn't appear to make any sense still working out, more so if you're a programmer.
Thanks in advance!!!
p.s: I already managed to find out everything else - charge timings, walk speed, slide speed, slide time etc. If you have interest on any of these, ask here or in a PM and I'll gladly pass on this information.
Help figuring out Megaman's jump curve - PLEASE!
I assume you've seen the information used by tool-assisted speedrunners? http://tasvideos.org/GameResources/NES/Rockman.html and http://tasvideos.org/GameResources/NES/Rockman/Data.html#JumpCurve for example?
The actual application of the deltas and rounding are probably just done directly in the code somewhere, it shouldn't matter where or be particularly important as long as you just apply the same rules (e.g., clamp Y speed to -12 when it gets below -12, et cetera).
Position fraction is probably representing an actual fraction in the form of (value)/256. This would make it the fractional portion of a fixed precision number, or what you could call a binary fraction.
You're writing position as 4.192, 3.128 - the actual position would be 4+(192/256) = 4.75, 3+(128/256) = 3.5. So it sounds like it's just applying normal rounding. The cheap way to apply this rounding is:
whole += (frac & 0x80) >> 7;
Fixed point numbers were really common before floating point hardware became normal. It's not surprising that an old NES game like Mega Man 5 uses it.
So 64 = .25, 128 = .5, 192 = .75
Gravity is also likely a binary fraction in the same format (is your fraction pattern correct? Seems wrong here).
EDIT:
In your own code, I would just use floats. There's probably no optimization to be had for using fixed point numbers in this case. You're just seeing a quirk of working with old hardware.
Thanks for the help, guys. I'll answer your posts below:
I assume you've seen the information used by tool-assisted speedrunners? http://tasvideos.org/GameResources/NES/Rockman.html and http://tasvideos.org/GameResources/NES/Rockman/Data.html#JumpCurve for example?
The actual application of the deltas and rounding are probably just done directly in the code somewhere, it shouldn't matter where or be particularly important as long as you just apply the same rules (e.g., clamp Y speed to -12 when it gets below -12, et cetera).
Yes, I've seen that site already, before asking this actually. It's good for getting the general idea, but I've seen some values which are actually wrong (using FCEUX Memory Watch myself). As I've said, I could do my own method using the general idea (which is what I'll probably end up doing anyway), but the actual Position Fraction incrementation that's being done doesn't make any sense to me, and I was curious about learning how it actually works.
Position fraction is probably representing an actual fraction in the form of (value)/256. This would make it the fractional portion of a fixed precision number, or what you could call a binary fraction.
You're writing position as 4.192, 3.128 - the actual position would be 4+(192/256) = 4.75, 3+(128/256) = 3.5. So it sounds like it's just applying normal rounding. The cheap way to apply this rounding is:whole += (frac & 0x80) >> 7;
Fixed point numbers were really common before floating point hardware became normal. It's not surprising that an old NES game like Mega Man 5 uses it.
So 64 = .25, 128 = .5, 192 = .75
Gravity is also likely a binary fraction in the same format (is your fraction pattern correct? Seems wrong here).
EDIT:
In your own code, I would just use floats. There's probably no optimization to be had for using fixed point numbers in this case. You're just seeing a quirk of working with old hardware.
The fraction pattern is actually right, and that's what's bugging me, honestly. If it wasn't for those values, I'd get the idea. If it fits you, you could test this on FCEUX. Using a Megaman 5 rom (not Rockman, the RAM positions for the US version are actually different), go to any stage, open the Memory Watch, type in the values I've provided in the OP, drop the emulation speed to something around 1% - 3%, jump, and watch the position fraction address. And see the bizarre pattern form :P
The fraction pattern is actually right, and that's what's bugging me, honestly. If it wasn't for those values, I'd get the idea.
Why don't you post the every position value (high and low, not just the fraction) and maybe I or someone else might see the pattern more clearly. No point in me duplicating the work you've already done just to help you finish, right?
Pretty fair. I'll be somewhat busy today, but by the end of the day I'll format this data into a table and put it here.
EDIT:
Here it is:
Last considerations: Concerning the Position, Speed High and Speed Low only (next I'll talk about the Position fraction), the Speed Low incrementations make sense, I get this (064 is the Gravity). But, what I don't get is... why sometimes it'll consider 128 being the threshold to do a round down (which makes sense, since 256/2 = 128), and why sometimes it won't (see for instance, when his speed is 2.128 while jumping, next frame he'll move 2 pixels, and the next and the next...).
Concerning the Position Fractions, they form a pattern indeed, but it doesn't seem to make any sense whatsoever.
gravity is applied to Y speed, not Y position. The Y speed low value pattern makes sense.
This speed is then subtracted from the Y position - (Y position low -= Y speed high; Y position fraction -= Y speed low).
Y position low and Y position fraction are, together, a normal 16-bit integer in which the lower 8 bits are representative of a fraction of a pixel.
Y speed high and Y speed low are the same - Y speed low is also a fraction of a pixel.