PPU Memory Access per-cycle list?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
PPU Memory Access per-cycle list?
by on (#58919)
If all PPU registers are 0, and the cart does absolutely nothing (or not present), what address does the PPU read per-cycle for a frame? IE:
0: 0x2000
1: 0x2000
2: 0x2000
3: 0x2001
4: 0x2001
5: 0x2001
6: 0x2001
7: 0x2001
8: 0x2001
9: 0x2001
10: 0x2001
11: 0x2002
12: 0x2002
13: 0x2002
14: 0x2002
15: 0x2002
16: 0x2002
17: 0x2002
18: 0x2002
19: 0x2003

I am trying to get cycle/pixel accurate using loopy_v/t. It would be a great resource if known cycle/pixel accurate emulators had this information in a table format.

I've looked at other emulators source, but a lot of them do not use the full PPU address space as laid out in an actual NES. IE: Access name tables via nametable[x] instead of PPU.Memory[0x2000 + x].

It's mostly hard to determine when to reset the address from the latch (V=T in loopy terms) during rendering cycles.

Thanks.
Re: PPU Memory Access per-cycle list?
by on (#58923)
beaub wrote:
what address does the PPU read per-cycle for a frame?

It's mostly hard to determine when to reset the address from the latch (V=T in loopy terms) during rendering cycles.

Thanks.


I certainly won't claim expert on this, but if you're looking for what the PPU is doing, NESICIDE2 gives a cycle-by-cycle dump. It includes real PPU fetches, garbage fetches, and the extra cycle. It also shows when the CPU is doing accesses to the PPU memory.

It is here. Unfortunately there's no installer yet but if you ask on #nesicide or here someone can probably build you one. [I'm hoping for some installer help!]

The dump I'm talking about is available in the Execution Inspector by clicking on "Show PPU Execution" checkbox. The Execution Inspector is in the menus View->Debugger->Execution Inspector.

by on (#58924)
Look at the Nintendulator source code. It's the easiest to read summary of what the PPU does at each cycle.

by on (#59075)
So what's the story with cycle 323 and 331?

It appears as though the PPU pre-fetches the last 2 tiles per-scan line and these cycles essentially setup the pre-fetched tiles to the right location in memory for the next scan line to fetch them from?

I noticed that after the first scan line, each line after that begins at an address 2 more than the previous one (2 tiles more).

Can someone explain this a bit better? Or acknowledge this? Is there a good document on what the hardware really does to pre-cache these tiles?

Thanks again.

by on (#59078)
beaub wrote:
So what's the story with cycle 323 and 331?

It appears as though the PPU pre-fetches the last 2 tiles per-scan line and these cycles essentially setup the pre-fetched tiles to the right location in memory for the next scan line to fetch them from?

I noticed that after the first scan line, each line after that begins at an address 2 more than the previous one (2 tiles more).

Can someone explain this a bit better? Or acknowledge this? Is there a good document on what the hardware really does to pre-cache these tiles?

Thanks again.


This is one of the reasons for the pre-render scanline, from what I can tell. It fills what I call the "pixel pipeline" for the first rendered scanline.

In each scanline the two tile fetches at the end of the scanline are for the next one.

Consider the case where the X-scroll is set to 7. That means that 1 pixel from the first tile and 7 pixels from the second tile need to be displayed right away when the PPU starts rendering the next scanline. If it had to fetch the data for those two tiles at the beginning of the scanline there'd be missing graphics on the left side [It takes 8 PPU clocks to fetch all the pieces required to render a tile, 1 NT byte, 1 AT byte, and 2 tile planes].

So the 2-tile fetches fill a 16-bit shift register ["pixel pipeline"] which is siphoned off at the X-scroll position when rendering the scanline. Then as the subsequent tiles are fetched they fill the second 8-bits of tte 16-bit shifter for seamless rendering.