Skip to content →

fixing smb

Now it’s time, to get things neat, and fix the two remaining problems in “Super Mario Bros.”

transfer tiles

As you can see on the right side of the screen, when scrolling, we get the wrong tiles, and they are off by 8 pixels to the top. It is easily recognizable, that we are pulling the tiles from the next row, without pulling the correct next tile to the right. This is, because I started out with just 16 tiles per row – static. But when we are scrolling, we actually have quite a few situations, where one line of tiles, accesses 17 tiles. 1/2 tile to the left, 15 in the middle, and 1/2 on the right, which is supposed to be the next upcoming tile. So, we need to take that into account and change the code accordingly. Luckily, this isn’t too much work.

We just need to change the part of our background drawing function, where we decide when to flip the Nametables. Since the tile with the sequential id 17 (or 16, when you count zero-based) can either be the transfer tile on our first row, or be the regular first tile on the second row, we need to identify when it is the first case. This can easily be achieved by checking our column counter. If it is beyond half of the screens width, and the tile has the sequential id 17 (16 0-based), we can be sure it is a transfer tile.

if (((natural_address & 0xffe0) != (scrolled_address & 0xffe0)) || ((col > 128) && ((tile_id % 32) == 0)))		//	check if X-boundary crossed ( AND account for transfer-tile glitch)
{
	scrolled_address ^= 0x400;	//	XOR the bit, that changes NTs horizontally
	scrolled_address -= 0x20;	//	remove the 'line break'
}

This will leave us with this result.

glitching ui

As you can see, the UI is glitching out, as soon as the first NT has scrolled out of the viewport to the left, and comes back to normal, as soon as the first NT is back on screen. This took quite a bit of time to debug, but it turned out, that the UI had the wrong base nametable address at the moment it disappeared. So, to fix this, we will reset the base nametable on every prep-scanline.

else if (ppuScanline == 261) {
//	VBlank off / pre-render line
if (ppuCycles == 1) {
	PPU_STATUS.clearVBlank();
	PPU_STATUS.clearSpriteZero();
	NMI_occured = false;
	PPUSCROLL_x = 0;
	PPUSCROLL_y = 0;
	PPU_CTRL.reset();
}

This fixes the glitching menu, and will leave us with a proper SMB demo. Important: this is NOT the final implementation!

Comments

Leave a Reply