It is currently Mon Oct 15, 2018 1:07 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Wed Jul 18, 2018 10:55 pm 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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.


Attachments:
dk2.png
dk2.png [ 22.61 KiB | Viewed 1668 times ]
dk1.png
dk1.png [ 21.05 KiB | Viewed 1668 times ]
Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 12:43 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3629
Location: Mountain View, CA
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


Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 10:14 am 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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.


Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 11:58 am 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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?


Attachments:
dk2.png
dk2.png [ 21.66 KiB | Viewed 1610 times ]
dk1.png
dk1.png [ 20.91 KiB | Viewed 1610 times ]
Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 1:25 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3629
Location: Mountain View, CA
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.


Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 8:43 pm 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
@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.


Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 9:21 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1994
Location: Fukuoka, Japan
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.


Top
 Profile  
 
PostPosted: Thu Jul 19, 2018 10:46 pm 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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.


Top
 Profile  
 
PostPosted: Fri Jul 20, 2018 12:57 am 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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.


Attachments:
dk2.png
dk2.png [ 21.5 KiB | Viewed 1529 times ]
dk1.png
dk1.png [ 22.21 KiB | Viewed 1529 times ]
Top
 Profile  
 
PostPosted: Fri Jul 20, 2018 7:38 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 817
Location: New York, NY
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.


Top
 Profile  
 
PostPosted: Fri Jul 20, 2018 11:15 pm 
Offline
User avatar

Joined: Mon Jul 16, 2018 2:57 pm
Posts: 20
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group