Hi, I'm writing my NES emulator in C++, but I'm stuck implementing the PPU.
I 'm trying to implement pixel accurate rendering, but iI have some problems with timing.
If I display the nametable manually fetching the tiles and the palettes at the end of the frame I get a correct output:
If I output the screen pixel by pixel it just shows garbage (kind of):
I can provide the code if necessary.
I can't get it right...
NES PPU pixel accurate rendering problems
Moderator: Moderators
Re: NES PPU pixel accurate rendering problems
First thing I recommend fixing is the fine Y coordinate, it seems stuck on a constant value.
Coarse Y seems to have a shifting error, maybe 2 too many bits to the right.
Palette and X seem fine.
Coarse Y seems to have a shifting error, maybe 2 too many bits to the right.
Palette and X seem fine.
Re: NES PPU pixel accurate rendering problems
I double and triple checked the code and the fine Y seems to increment correctly and so does the coarse Y.
But it seems like you say, since the patterns are repeated two times and it seems to go outside the correct frame (the verical bands).
How can I debug it? It's been two days, I am missing something here..
Re: NES PPU pixel accurate rendering problems
You can post your code here.
The increment may be fine but how the Y value is used could be questioned. Have you tried placing a breakpoint on rendering the second scanline?
I just noticed that the nametable is repeated twice before showing the next nametable. So I'm assuming you're recalculating Y every single time. Tile address should be "0010 NNYY YYYX XXXX" where "NN" is always "YX" regardless of nametable dimensions (unlike SNES).
Don't be afraid to make more debugging tools or experiments. For example, draw a RGB representing either fine or coarse coordinates rather than the final color.
The increment may be fine but how the Y value is used could be questioned. Have you tried placing a breakpoint on rendering the second scanline?
I just noticed that the nametable is repeated twice before showing the next nametable. So I'm assuming you're recalculating Y every single time. Tile address should be "0010 NNYY YYYX XXXX" where "NN" is always "YX" regardless of nametable dimensions (unlike SNES).
Don't be afraid to make more debugging tools or experiments. For example, draw a RGB representing either fine or coarse coordinates rather than the final color.
Re: NES PPU pixel accurate rendering problems
I rewrote the PPU from scratch, and at first it was showing this:Myself086 wrote: ↑Thu Mar 12, 2020 8:29 am You can post your code here.
The increment may be fine but how the Y value is used could be questioned. Have you tried placing a breakpoint on rendering the second scanline?
I just noticed that the nametable is repeated twice before showing the next nametable. So I'm assuming you're recalculating Y every single time. Tile address should be "0010 NNYY YYYX XXXX" where "NN" is always "YX" regardless of nametable dimensions (unlike SNES).
Don't be afraid to make more debugging tools or experiments. For example, draw a RGB representing either fine or coarse coordinates rather than the final color.
I don't know why the previous (identical) implementation was wrong, but now I have a starting point to debug the PPU.
After a whole day I found out that the issue is in the way I represent the internal VRAM address registers: bit-fields
Code: Select all
union
{
struct
{
uint16_t coarseX : 5;
uint16_t coarseY : 5;
uint16_t baseNametableAddressX : 1;
uint16_t baseNametableAddressY : 1;
uint16_t fineY : 3;
uint16_t unused : 1;
} bits;
uint16_t reg;
} addressT, addressV; // temporary VRAM adddress register and VRAM address register
Code: Select all
union
{
struct
{
uint8_t coarseX : 5;
uint8_t coarseY : 5;
uint8_t baseNametableAddressX : 1;
uint8_t baseNametableAddressY : 1;
uint8_t fineY : 3;
uint8_t unused : 1;
} bits;
uint16_t reg;
} addressT, addressV; // temporary VRAM adddress register and VRAM address register
Now the rendering function is working fine, I don't know how the type of the bit field influences the whole register. I'm going to study that aspect of the language, because it was surely a really nasty bug!
Re: NES PPU pixel accurate rendering problems
For what it's worth, in all of the places I've used bitfields in my own emulator (which is currently restricted to mappers), I've always specified types of "signed" or "unsigned" rather than types which imply specific widths (e.g. "unsigned coarseX : 5;").
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: NES PPU pixel accurate rendering problems
Oh wow that's a nasty bug haha. Did you happen to debug and see what values it was producing??
Re: NES PPU pixel accurate rendering problems
It was storing adjacent bit fields without crossing allocation unit boundaries. I learned the hard way that bit fields are implementation (aka compiler) defined behavior, I'm using Visual Studio 2019. So using uint16_t It was storing different bitfields in different 16-bit allocation units, padding the rest. So the value was different when accessing the register as a 8-bit word than when accessing individual bit fields.
Hence a very nasty bug.