Don't think I've screwed up anywhere, but would be nice to have some third-party verification. beannaich?
spr0_hit and vid_ are good nodes to watch.
Moderator: Moderators
Code: Select all
======== (1) ========
This starts, stops, and resets the simulation. The 'Scanline:' and 'Pixel:'
status displays are based on internal PPU counters and should be
self-explanatory. The starting state to use when resetting the simulation can
be selected with the radio buttons near (5).
======== (2) ========
This is a list of register accesses to be carried out, going in sequence from top
to bottom. The simulated 2C02 isn't attached to any other simulated devices, and
the way to access registers is by adding them to this list. For example, 'W 1 1e'
decodes as 'write $1E to $2001'. Reads can be significant for some registers,
which is why they're included. (Note that you don't get any value "back" for reads
though.)
Register accesses can be removed by clicking on the '-' and added by clicking
on the '+'. A '-' in the R/W colum means 'no-op' (use the numpad to input the
'-').
The '*' is just to show the current access. You can click on it to jump to that
point in the sequence.
======== (3) ========
Memory display. Can also be used to modify memory.
- 3F00-3F1F is the palettes. Some of the cells are mirrors.
- S000-S11F is OAM. For example, S000 would be the y position for sprite 0.
* S000-S0FF is the primary OAM.
* S100-S11F the secondary OAM (normally not directly accessible).
- 0000-03FF is the pattern tables. This 1KB segment is mirrored eight times
to fill out the entire CHR space.
- 2000-23FF is nametables. The simulation uses a kind of "one-screen low"
mirroring, and the data here is mirrored to fill out the entire nametable
space.
======== (4) ========
This is a video output waveform display. It's based on the vid_ node. If you
run the simulation without changing anything first, you will just see some
level changes and squiggly stuff here near the end of each scanline, which is
the NTSC hsync/colorburst, etc.
======== (5) ========
Pretty self-explanatory. Node numbers or node names (e.g. "spr0_hit") can be
entered in the Find: box to locate them in the diagram. (This won't be used
here.)
======== (6) ========
Tracing stuff. Additional nodes to trace can be added in the "Trace these too:"
box as a space-separated list (e.g. "spr0_hit tile_l vid_").
The cycle column is based on the master clock, which the PPU divides by four.
Each line in the trace is actually a half-cycle, so there's 4*2 = 8 lines per PPU
tick.
======== Finding nodes to trace =======
A list of nodes can be found in
http://www.qmtpro.com/~nes/chipimages/visual2c02/nodenames.js . For nodes that
have many bits, e.g. finex0, finex1, finex2, you can trace all of them at once
by using 'finex' as the node name.
======== Performance hint ========
Turning off tracing and unticking "Animate during simulation" and "Show sprite
RAM contents" can massively speed up the simulation.
======== Tutorial: Outputting some pixels =======
1. Put 81 at pattern table address 0000. This will make the palette index for
each pixel of the first row of the first tile, in order, '10000001'. (Putting
81 at 0008 as well would make it '30000003', etc.)
(Since the nametables are initialized to 0 by default, this is the tile that
will be used for all the background tiles by default.)
2. Change the value of 3F01, which is the BG palette entry that will be used.
20 seems to work fine.
3. Run the simulation (and note the Performance section). The first line is the
pre-render line, so nothing will be seen here. At scanline 1, you should see
some pixels being output in the waveform display corresponding to the 81
pattern.
======== Some things to look out for ========
- Note that the default register writes might move around sprite 0 and do
other stuff, so you might have to remove some of them or manually modify
memory later to get the state you want.
- There's a bunch of sprites sitting at (0,0). If sprites are enabled and all
use a black tile, this means you will see black for the first 8 pixels of
scanlines 1-8 (sprites don't start drawing until scanline 1 at the earliest
since the y OAM coordinate is one less than the actual position).
I'll be confirming a lot of this information as I begin implementing this into my emulator.ulfalizer wrote:Don't think I've screwed up anywhere, but would be nice to have some third-party verification. beannaich?
I could never get low level rendering to work until I had a firm grasp on high level operation. That should be the natural progression of any emulator, start at high level, slowly convert things to low level. Anyone using the PPU diagram when writing a new emulator, especially with no previous experience, all I have to say is "Good luck".ulfalizer wrote:After some discussion in #nesdev I felt a little bad about maybe making basic emulator implementation seem way trickier than it really is, so I added a note to the diagram.
Code: Select all
(ppu->*runStep[screenX][screenY])();You are right.tepples wrote:An array of 90,000 function pointers would kill your cache.