Sorry for the lack of updates!
Yes, as some people here already know, a new Rockman movie is being made.
I’m playing it, and AngerFist is also contributing.
We’re currently in the middle of the Iceman stage.
The progress can be followed, or at least deduced, from the usual location:
http://tasvideos.org/Bisqwit/RockmanMovie.html
Sorry, we’re not releasing WIPs yet.
Yesterday, I made some discoveries regarding this game.
It really helps when I have these tools ― it actually surprises me too ― that report some things regarding the game.
* It tells precisely each frame what speed Rockman is moving and accelerating in each direction
* It tells when the game lags
* It tells when an enemy has been hit (and the number of remaining hitpoints)
* It tells when an item has been picked
* It tells the location and extent of each magnet beam (so I don’t need trial&error to see where it reaches)
* It tells when the screen starts scrolling
All this is very useful in
measuring and comparing different ways of acting.
It also saves effort, because I don’t need to do so much trial&error when I get the results earlier in a human-readable form.
I will attach the source code later in this post.
Discovery number 1: Y speed and position fluctuates when walking a lift/beam
Rockman’s Y speed and position are in constant fluctuation when he’s walking on a beam. It is stable when he walks on ground.
This was recorded while walking on ground:
. Playing frame 11806 - rockman Y=116.00 (−0.75)
. Playing frame 11807 - rockman Y=116.00 (−0.75)
. Playing frame 11808 - rockman Y=116.00 (−0.75)
This was recorded while walking on a beam:
. Playing frame 11970 - rockman Y=33.17 (−6.13)
. Playing frame 11971 - rockman Y=33.30 (−6.38)
. Playing frame 11972 - rockman Y=33.68 (−6.63)
. Playing frame 11973 - rockman Y=33.31 (−6.88)
. Playing frame 11974 - rockman Y=33.19 (−7.13)
The number in parenthesis is his Y speed.
Apparently, the whole time he walks on a beam, his Y speed increases as if he was falling, but the beam forces him above it.
This explains why Rockman suddenly falls at high speed when the beam stops carrying him.
He falls at the speed he would fall if he had been falling the whole time he walked on the beam.
When he walks on normal platforms, his vertical speed is a stabile −0.75. The maximum speed is −12.00, as shown below.
. Recording frame 11990 - rockman Y=33.25 (−11.13)
. Recording frame 11991 - rockman Y=33.38 (−11.38)
. Recording frame 11992 - rockman Y=33.76 (−11.63)
. Recording frame 11993 - rockman Y=33.39 (−11.88)
. Recording frame 11994 - rockman Y=33.27 (−12.00)
. Recording frame 11995 - rockman Y=33.27 (−12.00)
. Recording frame 11996 - rockman Y=33.27 (−12.00)
Btw, this also gives away the formula of Rockman's fall-acceleration: 0.25 added to YSpeed every frame, and YSpeed added to YPos every frame.
So, the significance of this discovery? Well. Sometimes you want to set up a beam en-route down from a zipping. The beam has to be placed on exactly the right height of course, but the options you are given depend on the speed you fall. By adjusting the time you spend on the beam, you can also adjust the speed you fall, and therefore, ultimately, the positions you can possibly put a beam on during the falling.
Discovery number 2: Game forces a limit on Y coordinate… sort of.
Background information: The Y coordinates of the game go so that 0=screen top, 239=screen bottom.
Because the datatype used to represent the coordinates is just 8-bit, it also acts simultaneously as a signed datatype.
Y coordinate −1 is therefore equal to 255, and −2 is equal to 254, and so on.
(This is the reason why you can grab a screen-bottom ladder from the screen top.)
Y coordinate −8 (248) indicates a dead character.
Normally, when Rockman jumps from a place that's near the top of the screen, the game prevents Rockman’s Y position from ever decreasing below −4.
However, he can land on a magnet beam that forces his position to be −5. That is precisely the height that it needs to be in order to zip through screen top.
However, if he tries jumping on a magnet beam that forces his Y position be −3..−5, his Y position will instantly become −8 (which indicates a dead character), and therefore he will die. That is, unless the screen can scroll below.
Discovery number 3: Walking speed, jumping speed
How Rockman walks and jumps, these have been an issue of question for a long time.
We have calculated that Rockman moves 1,1,2,1,1,1,2,1,1,2, pixels per frame, and so on.
We have also made theories that certain jumps slow down Rockman (7-frame jumps slow down 1 frame,
14-frame jumps slow down 2 frames)...
It’s time to throw out the window, this nonsense.
First, some background information.
In Rockman 1 (also in Rockman 2), there are the following variables defining Rockman's position and movement speed.
* Screen_number. This is an unsigned 8-bit integer.
* X_position, Y_position, X_speed, Y_speed. These four are decimal numbers that contain a 8-bit integer part and a 8-bit decimal part.
Every frame, the game does this to Rockman’s position:
X_position = X_position + X_speed
Y_position = Y_position − Y_speed
If X_position overflows, the carry will be added/subtracted from/to the Screen_number.
When Rockman walks, his X_speed is precisely this value 1.375.
When Rockman jumps or falls, his X_speed is this value: 1.312.
From the screen, you can only observe the integer part of his position, but the game actually tracks a quite precise subpixel position.
This means:
* When walking, it takes 73 frames to reach the distance of 100 pixels.
* When falling or jumping, it takes 76 frames to reach the distance of 100 pixels.
Obviously, this means that now we have a
good reason to encourage Rockman players to do as small jumps as possible and as few jumps as possible.
Note: The X-speed during jumping/falling does not depend on the height or speed of the jump.
All jumps work the same way.
Discovery number 4
In the Iceman stage, after the shutter, it is faster to
not jump after the shutter to regain motion fast. The combined ”Rockman stands still trying to start walking” and ”sliding on the ice” is faster than the jumping movement. The difference is a mere 1 pixel, but it's a difference nonetheless.
So, the source code.
* Megaman and magnet beam meters (file=movie.c):
void FCEU_DrawMovies(uint8 *XBuf)
{
if(frame_display && current != 0 && last_frame_display!=framecount)
{
extern unsigned char RAM[0x800];
double RockY = (unsigned short)(RAM[0x600]*256 + RAM[0x620])/ 256.0;
double RockYS = (signed short )(RAM[0x680]*256 + RAM[0x660])/ 256.0;
double RockX = (unsigned short)(RAM[0x480]*256 + RAM[0x4A0])/ 256.0 + RAM[0x460]*256;
double RockXS = (signed short )(RAM[0x4C0]*256 + RAM[0x4E0])/ 256.0;
unsigned Beam1Y = RAM[0x5F0];
char msg[512];
sprintf(msg, " - X=%.2f%+.3f Y=%.2f%+.3f\nBeams:%u,%u-%u; %u,%u-%u; %u,%u-%u; %u,%u-%u; %u,%u-%u\n",
RockX,RockXS, RockY, RockYS,
RAM[0x5D5]*256+RAM[0x5C5], RAM[0x5F5], RAM[0x5D5]*256+RAM[0x5C5]+16*RAM[0x5A5],
RAM[0x5D6]*256+RAM[0x5C6], RAM[0x5F6], RAM[0x5D6]*256+RAM[0x5C6]+16*RAM[0x5A6],
RAM[0x5D7]*256+RAM[0x5C7], RAM[0x5F7], RAM[0x5D7]*256+RAM[0x5C7]+16*RAM[0x5A7],
RAM[0x5D8]*256+RAM[0x5C8], RAM[0x5F8], RAM[0x5D8]*256+RAM[0x5C8]+16*RAM[0x5A8],
RAM[0x5D9]*256+RAM[0x5C9], RAM[0x5F9], RAM[0x5D9]*256+RAM[0x5C9]+16*RAM[0x5A9]
);
FCEU_DispMessage("%s #%u%s",(current<0) ? "Play" : "Rec", framecount, msg);
last_frame_display = framecount;
return;
}
if(!MovieShow) return;
FCEU_DrawNumberRow(XBuf,MovieStatus, CurrentMovie);
MovieShow--;
}
* Action indicators (file=bisqbot.cc, called from X6502_RunNormal):
static bool sound=false;
if(PC == 0xD54C) sound=true;
if(PC == 0xD56E) sound=false;
if(!sound && PC == 0xA238) FCEU_DispMessage("Damage from enemy %02X (%u points)\n", Y,A);
if(!sound && PC == 0xBEDF) FCEU_DispMessage("Enemy %02X hit with weapon %u (%d points left)\n",
Y, RAM[0x5F], (signed char)A);
if(!sound
&& (PC == 0x9FE8)) // horiz scrolling
{
FCEU_DispMessage("Scrolling routine at PC=%04X A=%02X X=%02X Y=%02X\n", PC, A,X,Y);
}
if(!sound
&& (PC == 0x925D)) // scroll prev room
{
FCEU_DispMessage("Scroll previous room at PC=%04X A=%02X X=%02X Y=%02X\n", PC, A,X,Y);
}
if(!sound
&& (PC == 0x92A6)) // scroll next room
{
FCEU_DispMessage("Scroll next room at PC=%04X A=%02X X=%02X Y=%02X\n", PC, A,X,Y);
}
if(PC == 0xC912)
{
FCEU_DispMessage("Boss %u damaged with weapon %u (%d points left)\n", RAM[0xAC], RAM[0x5F], (signed char)A);
}
if(PC == 0xC833)
{
FCEU_DispMessage("Acquire item %u\n", A);
}
if(PC == 0xD4B1) FCEU_DispMessage("LAG detected\n");