Made some progress would like your PPU advice...

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Made some progress would like your PPU advice...
by on (#221477)
Hi All,

Thanks for all of the advice about the Mac emulators. I eventually settled on Nintaco. Well, I finally got my PPU rendering some basic backgrounds (turns out I had a few CPU bugs I didn't realize before (now I'm passing everything in nestest until the first non-standard instruction) and by not turning off rendering when flags were set, scroll code was causing V to get too large). I've attached the screenshots of where I'm at now with Donkey Kong.

I figured the extremely experienced devs on here could probably take one look at these attached screenshots and instantly know what problems I should tackle next in my PPU to get it rendering backgrounds decently. My code is here:
https://github.com/davecom/DDNES

Thanks in advance!

Edit: Updated screenshots after fixed off by 1 tile error.
Re: Made some progress would like your PPU advice...
by on (#221482)
Looks like your attribute table calculation/bits are wrong, or how you're handling/doing palettes. First screenshot implies more of the former than the latter.

Edit: could also be that the attribute table you have is correct, but the palette indices (or even your palette/colour values themselves) are wrong.

Best thing to do is use an emulator like FCEUX or Nintendulator or Mesen or NO$NES to examine the relevant details using the same game + compare to your own. I've used FCEUX and NO$NES for this purpose in the past, but I imagine Mesen does a pretty good job too. But I'll help best I can:

At power-on (not reset), using ROM Donkey Kong (W) (PRG1) [!] (MD5 6d4a94c344463e562344249e18e9b99f), the palette for the title screen looks like this, starting at palette index 0:

Code:
0F 2C 38 12  0F 27 27 27  0F 30 30 30  0F xx xx xx
00 25 xx xx  00 xx xx xx  00 xx xx xx  00 xx xx xx

Where xx means an uninitialised palette entry (FCEUX defaults to a dark-mid grey tone (RGB value 0x76, 0x76, 0x76), mainly to "simulate" the common "grey screen" the NES would show before the game had initialised PPU + palette + etc.), i.e. the game hasn't updated/changed/set those palette entries. On a reset, these values would remain whatever they previously were at the time of reset.

Immediately after starting the game, or during the attract demo, the palette becomes this (again starting at index 0):

Code:
0F 15 2C 12  0F 27 02 17  0F 30 36 06  0F 30 2C 24
00 02 36 16  00 30 27 24  00 16 30 37  00 06 27 02
Re: Made some progress would like your PPU advice...
by on (#221542)
koitsu wrote:
Looks like your attribute table calculation/bits are wrong, or how you're handling/doing palettes. First screenshot implies more of the former than the latter.

Edit: could also be that the attribute table you have is correct, but the palette indices (or even your palette/colour values themselves) are wrong.

Best thing to do is use an emulator like FCEUX or Nintendulator or Mesen or NO$NES to examine the relevant details using the same game + compare to your own. I've used FCEUX and NO$NES for this purpose in the past, but I imagine Mesen does a pretty good job too. But I'll help best I can:

At power-on (not reset), using ROM Donkey Kong (W) (PRG1) [!] (MD5 6d4a94c344463e562344249e18e9b99f), the palette for the title screen looks like this, starting at palette index 0:

Code:
0F 2C 38 12  0F 27 27 27  0F 30 30 30  0F xx xx xx
00 25 xx xx  00 xx xx xx  00 xx xx xx  00 xx xx xx

Where xx means an uninitialised palette entry (FCEUX defaults to a dark-mid grey tone (RGB value 0x76, 0x76, 0x76), mainly to "simulate" the common "grey screen" the NES would show before the game had initialised PPU + palette + etc.), i.e. the game hasn't updated/changed/set those palette entries. On a reset, these values would remain whatever they previously were at the time of reset.

Immediately after starting the game, or during the attract demo, the palette becomes this (again starting at index 0):

Code:
0F 15 2C 12  0F 27 02 17  0F 30 36 06  0F 30 2C 24
00 02 36 16  00 30 27 24  00 16 30 37  00 06 27 02


Thanks a lot for this, it's very helpful. My title screen palette memory matches yours exactly. My attract demo screen is very close, with just the second nibble of a few changes from 0 to F. I wonder if this is because I have a different version of the ROM. Whereas your attract demo palette is:
Code:
0F 15 2C 12  0F 27 02 17  0F 30 36 06  0F 30 2C 24
00 02 36 16  00 30 27 24  00 16 30 37  00 06 27 02

Mine is:
Code:
0F 15 2C 12  0F 27 02 17  0F 30 36 06  0F 30 2C 24
0F 02 36 16  0F 30 27 24  0F 16 30 37  0F 06 27 02


Since the colors are off on both my title screen and my attract screen I am thinking this is not a palette memory issue.
Re: Made some progress would like your PPU advice...
by on (#221556)
Okay, I'm an idiot. I was pulling each color directly from the NES palette (so limited to 8 colors) instead of first getting the entry from palette memory. As you can see in the attached screenshots, this is fixed now. But now I have some other problems to address, that maybe you have some insight about:
Title Screen:
- Extra white lines on the right hand side of the letters

Attract Demo
- The extra light brown line in the first set of barrels
- The extra white lines in Donkey Kong himself
- The extra red line in the oil barrel

What is the most likely cause of extra vertical lines? What's interesting is that they're different colors. I'm guessing a misalignment somewhere in the shift registers?
Re: Made some progress would like your PPU advice...
by on (#221566)
I can't tell you what the problem is, but I'd suggest looking at:

a) your drawing routine for pattern table (CHR) data,
b) any kind of calculation routine your emulator is using internally for correlating graphics on-screen <--> pattern table (CHR) data,
c) the actual CHR data (I doubt this is wrong, since for this game it's all in the ROM itself); make sure the ROM works on other emulators to rule out actual corruption (there are tons of bad ROMs floating around, that's why I gave filename AND MD5 checksum).

Honestly to me, it looks like some sort of off-by-one mistake, since it's either the first or last pixel in a tile's scanline. Edit: it looks like its the last pixel column on some tiles, i.e. the last/far right pixel.

For the title screen, the tile that makes up the word "DONKEY KONG" is tile $62 located in the 2nd pattern table. That may help you.

You should really give in and just install/use Wine and get some actual Windows emulators going to help you with analysis. You'll find FCEUX's debugger, PPU viewer, nametable viewer, and hex editor (to view different parts of memory space, including PPU) to be very helpful. Stop hemming and hawing over "a pretty UI", this is low-level work; the UI will be the last of your concerns when it comes to this type of troubleshooting, I can assure you.
Re: Made some progress would like your PPU advice...
by on (#221585)
@koitsu - thanks for the comprehensive reply. I'll look into it and report back. What's weird is it seems to only affect some tiles. If it was a generalized off by one error, I would expect to see it on almost all of the tiles... I wonder what can be off by one for only some tiles... I'll have to do some investigating.

koitsu wrote:
You should really give in and just install/use Wine and get some actual Windows emulators going to help you with analysis. You'll find FCEUX's debugger, PPU viewer, nametable viewer, and hex editor (to view different parts of memory space, including PPU) to be very helpful. Stop hemming and hawing over "a pretty UI", this is low-level work; the UI will be the last of your concerns when it comes to this type of troubleshooting, I can assure you.


It's not just the UI, it's the pain of having to install Wine which I recently uninstalled. I'm using Nintaco now which actually has all of the features you mentioned. But I will checkout FCEUX on my Linux or Window machine as well to compare. Thanks again.
Re: Made some progress would like your PPU advice...
by on (#221586)
If you don't like the command line based wine you can use wine bottler instead:

http://winebottler.kronenberg.org/

I have been using it at work for many years and it quite easy to use. The latest dev version support 2.0 too.
Re: Made some progress would like your PPU advice...
by on (#221589)
Banshaku wrote:
If you don't like the command line based wine you can use wine bottler instead:

http://winebottler.kronenberg.org/

I have been using it at work for many years and it quite easy to use. The latest dev version support 2.0 too.


Yeah I've used WineBottler before and it's pretty good.
Re: Made some progress would like your PPU advice...
by on (#221597)
Okay, I figured it out. The problem was that my high tile byte calculations were off by 1 when I was merging them into the shift register for rendering. Apparently a shift by a negative number is undefined in C, so it's a hard error to spot.

My old code looked like this:
Code:
for (int i = 7; i >= 0; i--) {
    temp_data <<= 4;                             
    temp_data |= ((low_tile_byte & (1 << i)) >> i) | ((high_tile_byte & (1 << i)) >> (i - 1)) | (attribute_table_byte );
}
tile_data |= temp_data;


Where tile_data is a 64-bit unsigned integer and temp_data is a 32-bit unsigned integer. Can you spot the error? What happens when i is 0? My new code looks like this:
Code:
for (int i = 7; i >= 0; i--) {
    temp_data <<= 4;
    temp_data |= ((low_tile_byte & (1 << i)) >> i);
    if (i > 0) {
        temp_data |= ((high_tile_byte & (1 << i)) >> (i - 1));
    } else {
        temp_data |= ((high_tile_byte & (1 << i)) << 1);
    }
    temp_data |= attribute_table_byte;
}
tile_data |= temp_data;


That was a subtle bug. Now I'm rendering Donkey Kong backgrounds correctly. Before I move on to sprites, what other Mapper 0 games do you recommend for testing when you have no sprites implemented and no controls implemented? Should I run any of the tests here:
https://github.com/christopherpow/nes-test-roms

Basically, I'm looking for background only tests.
Re: Made some progress would like your PPU advice...
by on (#221613)
davecom wrote:
Code:
for (int i = 7; i >= 0; i--) {
    temp_data <<= 4;
    temp_data |= ((low_tile_byte & (1 << i)) >> i);
    if (i > 0) {
        temp_data |= ((high_tile_byte & (1 << i)) >> (i - 1));
    } else {
        temp_data |= ((high_tile_byte & (1 << i)) << 1);
    }
    temp_data |= attribute_table_byte;
}
tile_data |= temp_data;


Your code might benefit from some precomputed lookup tables (LUT), each containing 256 elements. For example, a LUT for reversing the bits in a byte. And, 2 other LUTs for doing those bit extractions.
Re: Made some progress would like your PPU advice...
by on (#221658)
zeroone wrote:
davecom wrote:
Code:
for (int i = 7; i >= 0; i--) {
    temp_data <<= 4;
    temp_data |= ((low_tile_byte & (1 << i)) >> i);
    if (i > 0) {
        temp_data |= ((high_tile_byte & (1 << i)) >> (i - 1));
    } else {
        temp_data |= ((high_tile_byte & (1 << i)) << 1);
    }
    temp_data |= attribute_table_byte;
}
tile_data |= temp_data;


Your code might benefit from some precomputed lookup tables (LUT), each containing 256 elements. For example, a LUT for reversing the bits in a byte. And, 2 other LUTs for doing those bit extractions.


Thanks, that makes sense. I could see a LUT being a bit more readable and a bit more performant. Since this is just a learning project and I'm really not worrying about performance, I'll probably leave it since it's working, but if I was doing a more serious emulator, I probably would make the change.