Bad background color in SMB

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Bad background color in SMB
by on (#88593)
I'm trying to understand why I get random splotches of black in SMB: image

I tried debugging it for a particular pixel (152,52). The relevant info for that was:

nametableAddr=0x20D3
mem[nametableAddr]=0x24 (i.e. tile 0x24)
attributeAddr=0x23CC
mem[attributeAddr]=0x55 (i.e. 1-1-1-1 for 2-bit attribute sections - I choose the bottom-right one, but they're all the same in this case.)
bgPaletteIndexWithoutAttribute=0 (blue)
bgPaletteIndexWithAttribute=4 (0 +(1 << 2)) (black)

When I compare with Nintendulator, I get all the same answers, except that I can't verify that it's using 0x23CC as the attribute. I double-checked that by hand, and it seems to be the right address given the pixel coordinate. My palette's also line up with Nintendulator's, so that shouldn't be the problem.

Any clues what I might be doing wrong? The cute thing about this is invisible blocks always seem to get rendered as black, so they're easy to find. :D

by on (#88596)
Do $2007 reading delayed by 1 byte (Read goes into a buffer, current buffer gets read) and see if that improves it. Update X scroll every scanline...other than that I'm not sure what could be causing that. Good luck, somebody who probably has had that exact problem will post how they fixed it.

by on (#88597)
Check your writes to $2007 when PPU address is between $3F00-$3Fxx. Are you doing proper palette mirroring?

by on (#88598)
3gengames wrote:
Do $2007 reading delayed by 1 byte (Read goes into a buffer, current buffer gets read) and see if that improves it. Update X scroll every scanline...other than that I'm not sure what could be causing that. Good luck, somebody who probably has had that exact problem will post how they fixed it.

Thanks for the suggestions. I've already been buffering $2007 reads, but can you clarify what you mean by updating X scroll every scanline?

by on (#88599)
Zepper wrote:
Check your writes to $2007 when PPU address is between $3F00-$3Fxx. Are you doing proper palette mirroring?

My $2007 writes look like:

Code:
public void writeDataRegister(int byte_) {
  int address = resolveAddress(registers[ADDR_REGISTER]);
  if (address < 0x2000) {
    mapper.writePpu(address, byte_);
  } else {
    mem[address] = (byte) byte_;
  }
  registers[ADDR_REGISTER] += hasFlag(REGISTER_CTRL, CTRL_INCREMENT_FLAG) ? 32 : 1;
}

For palette mirroring, I seem to have the same values as Nintendulator. I had originally followed some WRONG doc that stated you needed to mirror 0x3F00 every four bytes. I'm now following what the wiki states, which seems to be accurate so far: "$3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C".

by on (#88600)
I think this is related to palette mirroring if the whole background were black and not blue. But it still could be. Are you making sure that whenever you write to the first palette entry of any part of the palette, that it changes all the values in the first position? Because it looks like maybe the color is right in some of the places but not all of them so depending on which background color palette is used for each tile it is correct or wrong.

Maybe you are mirroring properly to the 3F00 location but when rendering you are still using 3F04,3F08,3F0C. Make sure you write all 4 locations when any of the four are written. Maybe that will fix it.

by on (#88601)
foobaz wrote:
Zepper wrote:
For palette mirroring, I seem to have the same values as Nintendulator. I had originally followed some WRONG doc that stated you needed to mirror 0x3F00 every four bytes. I'm now following what the wiki states, which seems to be accurate so far: "$3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C".


You need to render with the color at $3F00 whenever the 2bpp from the tile data is 0, regardless of what the attribute bits are.

by on (#88602)
cpow wrote:
You need to render with the color at $3F00 whenever the 2bpp from the tile data is 0, regardless of what the attribute bits are.

Hallelujah! I didn't even need to try this to know it was the answer. I'm wondering if I just missed that or if it just isn't documented very well.

by on (#88603)
MottZilla wrote:
I think this is related to palette mirroring if the whole background were black and not blue. But it still could be. Are you making sure that whenever you write to the first palette entry of any part of the palette, that it changes all the values in the first position? Because it looks like maybe the color is right in some of the places but not all of them so depending on which background color palette is used for each tile it is correct or wrong.

Maybe you are mirroring properly to the 3F00 location but when rendering you are still using 3F04,3F08,3F0C. Make sure you write all 4 locations when any of the four are written. Maybe that will fix it.

For posterity's sake I'll point out that I mirror in resolveAddress (currently a hideous tangle of masks, if's and switches). So, for example, given 0x3F14 and 0x3F04, all reads and writes just go to 0x3F04. 0x3F14 is never written to or read from.

by on (#88604)
The only way to show the color in $3F04, $3F08, or $3F0C is to have the VRAM address pointed at them while rendering is turned off.

by on (#88633)
yes, i also had bad background colors in SMB when i started my emu. it was palette mirroring problems.

by on (#88634)
foobaz wrote:
Zepper wrote:
Check your writes to $2007 when PPU address is between $3F00-$3Fxx. Are you doing proper palette mirroring?

My $2007 writes look like:

Code:
public void writeDataRegister(int byte_) {
  int address = resolveAddress(registers[ADDR_REGISTER]);
  if (address < 0x2000) {
    mapper.writePpu(address, byte_);
  } else {
    mem[address] = (byte) byte_;
  }
  registers[ADDR_REGISTER] += hasFlag(REGISTER_CTRL, CTRL_INCREMENT_FLAG) ? 32 : 1;
}

For palette mirroring, I seem to have the same values as Nintendulator. I had originally followed some WRONG doc that stated you needed to mirror 0x3F00 every four bytes. I'm now following what the wiki states, which seems to be accurate so far: "$3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C".


You're not showing your $3ff0-3fff code. The same values don't mean correctness.