Made some progress would like your PPU advice...
Moderator: Moderators
Made some progress would like your PPU advice...
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.
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.
- Attachments
-
- dk2.png (22.61 KiB) Viewed 6303 times
-
- dk1.png (21.05 KiB) Viewed 6303 times
Re: Made some progress would like your PPU advice...
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:
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):
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: Select all
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
Immediately after starting the game, or during the attract demo, the palette becomes this (again starting at index 0):
Code: Select all
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...
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: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:
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.Code: Select all
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
Immediately after starting the game, or during the attract demo, the palette becomes this (again starting at index 0):
Code: Select all
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
Code: Select all
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
Code: Select all
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
Re: Made some progress would like your PPU advice...
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?
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?
- Attachments
-
- dk2.png (21.66 KiB) Viewed 6245 times
-
- dk1.png (20.91 KiB) Viewed 6245 times
Re: Made some progress would like your PPU advice...
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'seither 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.
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
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...
@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.
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.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.
Re: Made some progress would like your PPU advice...
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.
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...
Yeah I've used WineBottler before and it's pretty good.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.
Re: Made some progress would like your PPU advice...
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:
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:
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.
My old code looked like this:
Code: Select all
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;
Code: Select all
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;
https://github.com/christopherpow/nes-test-roms
Basically, I'm looking for background only tests.
- Attachments
-
- dk2.png (21.5 KiB) Viewed 6164 times
-
- dk1.png (22.21 KiB) Viewed 6164 times
Re: Made some progress would like your PPU advice...
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.davecom wrote:Code: Select all
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;
Re: Made some progress would like your PPU advice...
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.zeroone wrote: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.davecom wrote:Code: Select all
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;