In August 2011, an RP2C02G was depackaged and photographed. Within 3 days, I had traced the metal layer, 2 days later, I recorded the location of every via I could see.
14 months later, the chip was finally delayered; polysilicon was traced in about 5 days, diffusion after another 4 days, and buried contacts 1 day later.
After about a day spent processing the layer images, fixing mistakes, and various tweaking, I present to you:
The Visual 2C02The simulator currently has an old test program I wrote for it (which performs a sprite DMA and then tries to enable rendering), but it doesn't really accomplish much because the PPU takes at least a complete frame to come out of reset and actually start accepting writes to various registers (as observed and documented
here).
Names have been assigned to a preliminary set of nodes and buses:
- all of the external pins (and their corresponding internal signals)
- the pixel counter (hpos*)
- the scanline counter (vpos*)
- the SPR-RAM address (spr_ptr*)
- the I/O register signals (w2000, w2001, w2003, w2004, w2005a, w2005b, w2006a, w2006b, w2007, r2002, r2004, r2007)
- the VRAM address register (vramaddr_t* and vramaddr_v*) plus fine X scroll (finex*)
- the writable bits of $2000 (addr_inc, spr_pat, bkg_pat, spr_size, slave_mode, enable_nmi)
- the writable bits of $2001 (pal_mono, bkg_clip, spr_clip, bkg_enable, spr_enable, emph*)
- the readable bits of $2002 (spr0_hit, spr_overflow, vbl_flag)
- the $2007 read buffer (inbuf*)
If you find any other interesting nodes, let me know and I will add them when I get a chance.
Big day for the nesdev community indeed.
Congrats on the accomplishment, and many thanks for making this tool/wealth of knowledge available to us all.
EPIC! Might mess around with it one day just to really see what's going on.
Well done, this will be fun to study.
Very very cool! Will have to play with this later. Thanks Quietust!
With the RP2C02 fairly disassembled at this point, would reproductions, featuring RGB output (with the changes one would expect) be feasible?
This sure looks very interesting, but how am I supposed to use this ?
@mikejomffit : The NES PPU does not have RGB output, and it was never meant to have any. The output signal is composite by the very nature of how the NES palette works, and it can't be otherwise.
Bregalad wrote:
how am I supposed to use this ?
I'm having some trouble understanding how this works too... how am I supposed to control the PPU?
The really tall table on the far right is the test program. Each column has a particular meaning:
"-" - delete this instruction.
"*" - run this instruction next (the current instruction will have this highlighted)
"+" - insert a new instruction after this one.
"?" - instruction type: "R" reads, "W" writes, and "-" delays.
"#" - instruction address (i.e. $2000-$2007); for delays, this is ignored.
"##" - instruction data. For delays, this is the number of cycles to wait; the value will be filled in when the instruction finishes.
I've just replaced the sample program with a much shorter one (replaced the full sprite DMA with just setting the first and last sprites).
If you can think of a better interface for this, I welcome your suggestions (or, better yet, actual code) - the current interface was the initial prototype I threw together so it had an interface in the first place.
There's also the issue that, even on a very fast computer, it will take over an hour and a half of simulation just for the chip to get out of reset (with animation and tracing both turned off, it ran at about 60Hz out of the standard 21.477272MHz). It might be possible to run the simulator for that long, save a snapshot of it just before the important reset logic finishes, then restore to that snapshot on reset, but I'll need to do some more research into the inner workings of ChipSim before I can manage that.
Thanks for the instructions.
Quietust wrote:
it will take over an hour and a half of simulation just for the chip to get out of reset
Wow, that's insane.
Quote:
save a snapshot of it just before the important reset logic finishes
I was just about to suggest that.
I wonder what exactly the PPU does during reset though...
tokumaru wrote:
Quietust wrote:
it will take over an hour and a half of simulation just for the chip to get out of reset
Wow, that's insane.
That is pretty crazy, I guess that's a good reminder to wait the 3 frames to start writing to the PPU
One of the things we really wanted to investigate was the OAM corruption bug that happens when you disable rendering late when sprites are near, even when you are uploading a new set of sprites before the next time rendering is turned back on.
How is the PPU memory (graphics and nametables) handled now? Is it all RAM now? Is it nonexistent? Any way to get CHR-ROM from a file in there?
How about making some composite video square waves, and turning them into RGB pixels so you can see its output?
Congratulations Quietust
Being watching progress almost in real-time in skype chat )
I'm using another approach, to understand PPU functionality:
This is (still unfinished) transistor-level schematics of top-left piece of PPU (most interesting part).
org wrote:
This is (still unfinished) transistor-level schematics of top-left piece of PPU (most interesting part).
Ah, this is pretty interesting too.
I rearranged the data into a better format for further processing:
[net name string, has pull-up boolean, attached gates list, attached sources list, attached drains list]
Edit: use updated format on page 3
Bregalad wrote:
This sure looks very interesting, but how am I supposed to use this ?
@mikejomffit : The NES PPU does not have RGB output, and it was never meant to have any. The output signal is composite by the very nature of how the NES palette works, and it can't be otherwise.
I understand this. However, the R2C03+ series that was designed to have RGB output by means of the color look-up table can't be a far cry from the design of the 2C02. With the chip de-capped and more thoroughly understood, would re-implementing this capability be out of the question?
I've just updated the Visual 2C02 to reset at the very beginning of scanline 260 (by running it to scanline 260 over the course of about an hour, saving its state, and then changing the Reset button to just load that state instead) and also fixed a bug in the VRAM address T->V reload logic (missing buried contact). During this process, I've confirmed several details:
1. When you reset the PPU, it's at the first visible scanline (i.e. scanline 0), and it's not until the PPU reaches the first pre-render scanline (scanline 261, also known as "scanline -1" in numerous emulators) that it becomes possible to write to most of the I/O registers.
2. The "T->V (horizontal bits only)" transfer during each scanline (including the prerender one) happens at pixel 257, as previously observed.
3. The previously observed "T->V (all bits)" at cycle 304 isn't exactly correct - what's really happening is that the PPU copies the non-horizontal bits from T->V during every pixel from 280 through 304 inclusive (which happens to correspond to the HBlank pulse).
4. Reading/writing $2007 appears to start the I/O one pixel after the CPU read/write cycle finishes.
5. Writing $2004 appears to push the actual data into SPR-RAM one pixel after the CPU write cycle finishes and increment the address 1 cycle later. It isn't clear exactly when the memory controller latches the value to be written, but it's probably at the beginning of the CPU's write cycle, so going faster than the 2A03's sprite DMA would probably fail.
6. The above pixel numbers are actually off by 1 compared to the cycle numbers we currently know for the rendering process - a typical scanline appears to go as follows:
0 - junk (latched address $1000 but did nothing)
1-2 - read nametable byte of 3rd tile
3-4 - read attribute table byte of 3rd tile
5-6 - read pattern table byte of 3rd tile
7-8 - read pattern table byte of 3rd tile
9-16 - fetch 4th tile
17-24 - etc.
...
249-256 - fetch 34th tile
257-264 - fetch 1st sprite, resetting the horizontal scroll bits in the VRAM address
265-272 - fetch 2nd sprite
273-280 - fetch 3rd sprite, starting HBlank at the 2nd cycle of the final read
...
304-312 - fetch 7th sprite, ending HBlank at the 2nd cycle of the first read
313-320 - fetch 8th sprite
321-328 - fetch 1st tile (next scanline)
329-336 - fetch 2nd tile (next scanline)
337-338 - read nametable byte of 3rd tile
339-340 - read nametable byte of 3rd tile
The entire chip uses a 2-phase clock where the 1st phase is what updates the H/V counters and actually starts external memory accesses (it's when ALE|/RD|/WR get activated) and the second phase is what triggers changes in the video signal (e.g. hblank starts halfway through cycle 280 and ends halfway through cycle 305). When the CPU and PPU clocks are properly "synchronized", memory accesses from the CPU (which take 3 pixels to complete) will be noticed by the PPU at the beginning of the second pixel (which probably explains the difference between the above pixel numbers and the previously known cycle numbers), while reads don't actually sample their data until the very end of the 3rd pixel (according to some testing with the Visual 2A03).
This is all very initeresting things !
I must admit I am still not yet familiar with observing transistors on a die, especially considering this is old technology which I think uses exclusively NMOS transistors (no PMOS) which is extremely weird. If anyone could explain me basically how this works or point me to some explanation it would be great.
I know it's nothing new, but it's funny how the PPU actually fetches 34 tiles when only 33 can be displayed. It's also funny to see how they did the colour DRAM with plain capacitors. The caps seem even smaller than transistors which is very surprising to me.
PS : Do you guys remember this old demo which says "Emulation might never be perfect, if you agree press start" ? Well not only this demo did ironically not run properly on the real hardware, but also it was wrong, emulation might be perfect.
OAM:
(clickable)
including:
- OAM fetch and control logic
- OAM I/O buffer
- OAM RAS/CAS
- OAM DRAM
I identified some control lines, which may help.
Some PPU simulation here :
http://code.google.com/p/breaks/source/ ... RP2C02/SRC
Is is me, or OAM is actually SRAM, not DRAM as previously doccumented ?
Bregalad wrote:
emulation might be perfect.
...and slow! XD
Both palette RAM and OAM are using pair of transistors, forming dynamic bi-stable latch. So this is obviously DRAM.
org: I think you have the OAM row/word line's inverted, the rightmost line is high when all row bits are high, so shouldn't it be 31?
Yup, I'll update circuit tomorrow )
Originally it was in correct order, but at some moment they got inverted
(I think it was after I wrote OAM RAS simulator:
http://code.google.com/p/breaks/source/ ... /SRC/OAM.c and started to examine RAS outputs)
org wrote:
Both palette RAM and OAM are using pair of transistors, forming dynamic bi-stable latch. So this is obviously DRAM.
Specifically, each memory cell consists of two transistors which have one terminal connected to GND and the other terminal connected to the opposite transistor's gate - applying voltage to one side causes the other side to be pulled down to GND. There's no positive feedback between them, though - the voltage simply floats within the gate and needs to be refreshed every so often by isolating the bus, precharging it, then exposing one column of cells to the bus so that it boosts the "high" side closer to VCC (while the "low" side simply sucks the charge into GND).
If it were SRAM, there would be two inverters feeding into each other, which manifests itself (in NMOS) as 4 transistors (2 of which are just pull-up resistors) - most of the registers on the chip are implemented as "dynamic latches", which are effectively inverter loops with an extra transistor+selector in the middle so that it can be reloaded with an external value (i.e. from CPU write) instead of itself.
kyuusaku wrote:
org: I think you have the OAM row/word line's inverted, the rightmost line is high when all row bits are high, so shouldn't it be 31?
The OAM0-7 (but not OAM8) lines feeding into the row/column decoders are inverted from the actual SPR-RAM address register - the far right "row" of memory is indeed "row 0" (in that it's the one that gets contains the values at SPR-RAM addresses $00-$07). However, the address lines themselves are not only inverted, but they are also backwards - the column decoder at the top takes A0-A2+A8 (not A5-A8) and the row decoder in the middle takes A3-A7 (not A0-A4), all organized from bottom to top (i.e. OAM5/6/7/8 are actually A0/A1/A2/A8 and OAM0/1/2/3/4 are actualy A7/A6/A5/A4/A3).
This might help:
Edits:
Kind of funny that OAM and palette RAM make up 60% of the transistors.
I've auto-captured the NOT and NOR gates, 1151 of them. Useful? I'll attach them anyway...
The first element is the output net/node, the rest are inputs.
I appear to have run into a bug in ChipSim, and it's probably the same one that was causing bizarre glitches in the Visual 2A03's triangle channel. Whenever I attempt to write to $2005 or $2006, the toggle always clears itself when the write starts, seemingly because transistors are being turned on and off in the wrong order. I have an idea as to how I can fix it, but I'm not sure if it'll work.
Anyone have any ideas on how to group transistors for comprehensible textual output? I've refined the node (guess I can call it "node", eww) organization so I can walk through the schematic and fairly easily transcribe it to paper, since my netbook doesn't really have the screen space, but that gets old really fast when you have to write down and match node numbers.
Or know a schematic capture program with a simple design/symbol format that can beautify ratsnest output?
Blah, I wish I didn't notice this thread, oh how work and chores have suffered >_< I'm more interested in the schematic side of things but I even tried my hand at a simulator >_< >_< The design is solid, in theory, since it implements iterative (uniform for now) propagation. If anything it'll be friendlier than Visual6502's at <200 lines.
That's how I'm doing it ) At first I trace all layers of high resolution die photos:
http://breaknes.com/files/PPU/2C02G.zip(since I dont have delayered images I took diffusion layer from Quietust site, other layers are traced by myself)
Then I save it as PNG, cut some part and double the scale (original picture still too small to draw transistors).
Then I start to draw it piece by piece:
http://breaknes.com/files/PPU/OAM.zipCtrl-C -> Ctrl-V really helps to me, there are too many regular structures on the chip )
I tried to restore circuit from the node list, but its a mess.
From the information I've gotten on the Visual 6502 mailing list, it sounds like these timing glitches I'm running into will need to be handled on a case-by-case basis (the Visual 6502 and 6800 seemingly also had this problem and presumably had to be hand-tweaked) - I've reordered the transistors in the $2005/$2006 toggle and it seems to be working correctly now.
In the process of checking that, I've also confirmed several additional useful bits in the simulator:
1. Palette RAM works correctly - I've successfully written and verified a string of 00s (came back as 00), a string of FFs (came back as 3F), and an incrementing sequence 00-1F (which came back as
10,01,02,03,
14,05,06,07,
18,09,0a,0b,
1c,0d,0e,0f,
10,11,12,13,
14,15,16,17,
18,19,1a,1b,
1c,1d,1e,1f, just as expected).
2. The video signal generator also seems to be working correctly - I measured the timing of all the various regions listed on the
wiki page, and they matched 100% (though, for some reason, the "pulse" sometimes came out with the "left border" color - maybe it doesn't always show up?), and I also confirmed that the "active" region actually starts at "pixel" 4 (the second cycle of the 3rd tile's attribute read), which might be important for proper grayscale/emphasis timing.
org wrote:
That's how I'm doing it ) At first I trace all layers of high resolution die photos:
http://breaknes.com/files/PPU/2C02G.zip(since I dont have delayered images I took diffusion layer from Quietust site, other layers are traced by myself)
Original die photos can be found here:
http://uxul.org/~noname/visual6502/RP2C02G/aligned/viewhttp://uxul.org/~noname/visual6502/RP2C02G/alignedhttp://uxul.org/~noname/visual6502/RP2C02G
Here's an updated data set. It's in the most efficient format I can think of.
[node name, pulled up, [[driver's gate node, driver's opposite node]]]
Just eval() and dump lines into pull-up and driver dictionaries.
Each of the drivers are implied transistors. Since the redundancy in the previous data sets was confusing I tied each transistor to a single node, meaning there are lots of nodes without any drivers. Due to transmission gates there isn't a way to know which node to give the transistor to, so it's claimed first come first served, which doesn't always yield convenient results.
I purged the OAM and palette RAM cells since they took up 4560 of the 8773 nodes. The hard-earned cell nodes are listed for reference...
A few minor updates:
1. I found and fixed a few missing vias, both located near some of the sprite logic; any gate lists you've made should probably be regenerated. Specifically, nodes 755 (connected to t4167) and 10662 (connected to t6212) should now be node 2 (i.e. GND).
2. I also reordered a few transistors in the secondary OAM address counter (so that it increments properly during the "initialization" that takes place during the first 64 pixels of each scanline).
3. I've identified a few more areas of interest - the secondary OAM address counter mentioned above (and the signal which selects between it and "primary" OAM), part of the sprite logic (a pair of shift registers up at the top which are fed from D0-D7 or D7-D0 based on the horizontal flip bit), and the location of the $2007 write buffer: open bus. Yes, that's right - when you write to $2007 to store data in VRAM, the actual byte you wrote sits on the internal I/O data bus for a few cycles before going out to the data pins, so writing to another register too soon (less than 3 CPU cycles later) will cause that value to be overwritten.
I've also identified some more stuff that doesn't simulate properly:
1. Sprite evaluation - when it tries to increment to "next sprite", it occasionally skips over a whole bunch of them, likely because some of the transistors connected to the clock lines are triggering in the wrong order (e.g. PCLK0 goes low and PCLK1 goes high [or vice-versa], there's a brief instant where both are high which causes things to glitch). I'm not sure I know how to solve this.
2. Writing to $2007 - for some reason, the "open bus" value is decaying after about 1 pixel instead of remaining indefinitely (on a real PPU, it lasts a significant amount of time), most likely due to a similar clock glitch, and the result is that the bottom 8 bits of the VRAM address end up getting written instead. If you insert an immediate write of the same value to $2002, then it'll get written properly.
[edit]
Just spotted and fixed another error in the logic for sprite #6 (2nd from the left) which was hardwiring one of its outputs to VCC (and also creating a short between VCC and GND that the netlist generator somehow missed).
Quietust wrote:
Yes, that's right - when you write to $2007 to store data in VRAM, the actual byte you wrote sits on the internal I/O data bus for a few cycles before going out to the data pins, so writing to another register too soon (less than 3 CPU cycles later) will cause that value to be overwritten.
That sure trashes our hopes of ever implementing a DMA feature that writes to $2007 as fast as the sprite DMA writes to $2004, doesn't it?
Well, 3 cycles is still better than 6 (LDA #$XX STA $2007), 7 (LDA $XX STA $2007), or 8 (LDA $XXXX, X STA $2007), which are currently the fastest ways to write to VRAM.
People, could someone convert those transistor based schemes into standard logic ones? I want to make functional copy of PPU in CPLD with non composite output. The big idea is get functional correct copy of PPU with component output (YPbPr). Because i think RGB is not correct output for NES/FAMICOM PPU and component YPbPr much closer to YUV. Thus PbPr will formed from number of color phase and Y from luma and sync. Does anyone ever think about this?
HardWareMan wrote:
People, could someone convert those transistor based schemes into standard logic ones? I want to make functional copy of PPU in CPLD with non composite output. The big idea is get functional correct copy of PPU with component output (YPbPr). Because i think RGB is not correct output for NES/FAMICOM PPU and component YPbPr much closer to YUV. Thus PbPr will formed from number of color phase and Y from luma and sync. Does anyone ever think about this?
Many times.
There's actually enough information in the 2C02's output to completely reconstruct the original color data, all 9 bits of it. The parts for it are even fairly affordable.
I think the real modern problem is that very few modern televisions do the right thing with a 240p signal, and upscaling the output is kind of a pain. But to add insult to injury, even if we added an upscaler, I don't know how many televisions will do the right thing (by which I mean "not add latency") for 480p input.
lidnariq wrote:
There's actually enough information in the 2C02's output to completely reconstruct the original color data, all 9 bits of it.
Even considering that the color emphasis bits appear to have sub-pixel resolution? I don't remember the details, but I think blargg discovered this a while ago.
When I described this technique, I hadn't considered emphasis.
tokumaru wrote:
lidnariq wrote:
There's actually enough information in the 2C02's output to completely reconstruct the original color data, all 9 bits of it.
Even considering that the color emphasis bits appear to have sub-pixel resolution? I don't remember the details, but I think blargg discovered this a while ago.
Ok, not subpixel. But that's 2C07 only, and I was under the impression (because of how much slower the CPU was) you couldn't consistently align it to one pixel, so as long as it's acceptable to snap emphasis to pixel boundaries it should still be doable.
tepples wrote:
When I described this technique, I hadn't considered emphasis.
Yeah, I sat down and generated a lookup table of all pixel-long=8-sample sequences; there are 425 of them for every single combination of color and emphasis. An extra counter is required to keep track of phase, because of the fpart(341×2÷3) and so colors $31 and $35 and $39 can produce the exact same 8-sample sequence. Several colors are indistinguishable once allowing for -30dBFS noise; e.g. color $10 with red emphasis quantizes as the same as color $32 with all emphasis bits set.
I found that bottom-left piece of PPU is actually sprite FIFO:
http://code.google.com/p/breaks/wiki/PPU_OAM_FIFOSome information on russian, Google translate helps you
Yes, that's one of the things I spotted yesterday:
Quietust wrote:
part of the sprite logic (a pair of shift registers up at the top which are fed from D0-D7 or D7-D0 based on the horizontal flip bit)
I also confirmed that the far-right column is for the first sprite and the far left column is for the 8th sprite, based on the priority logic directly above them.
Also, the bit at the very bottom-right of that area is the $2007 read buffer (D0-D2 on the bottom, a gap, and then D3-D7 at the top).
OAM FIFO circuit:
Small circuit on upper-right corner of FIFO is acutally sprite H-inversion logic.
Ah, and a weird tangle on the top is some kind of sprite color selector, which select pixel color in case more than single sprite hit the spot.
Ugh, just noticed I have wrong FIFO order
Nevermind )
org wrote:
Small circuit on upper-right corner of FIFO is acutally sprite H-inversion logic.
Yep, that's the bit I was referring to in my previous post.
org wrote:
Ah, and a weird tangle on the top is some kind of sprite color selector, which select pixel color in case more than single sprite hit the spot.
That's actually how I determined that sprite 0 is on the right and sprite 7 is on the left - the one on the far left requires not only for sprite 7 to be outputting a visible pixel but also for sprites 6-0 to
not be outputting a visible pixel, while the one on the far right just has the check for itself (and also has some additional logic to activate sprite 0 hit).
I noticed you pointed out an "oddity" in the middle of the H position counter where the carry input for bit 5 is actually bits 0 thru 4 ANDed together (actually the inverted bits 0-4 NORed together) rather than the carry output for bit 4; I observed this same thing in the master H/V counters at the top of the chip, and I can only assume that it was some sort of protection from timing glitches.
It'd also be nice if you could match up some of the signals you've named with node numbers in Visual2C02 so I can add them to nodenames.js and make it easier for others to trace signals around.
Quote:
I can only assume that it was some sort of protection from timing glitches.
I'm calling this thingy: "a twist". Look how these sort of counter work (on H/V example) :
Code:
iterations:
0: H=0 V=0
1: H=478 V=479
2: H=478 V=479
3: H=32 V=32
4: H=32 V=32
5: H=446 V=447
6: H=446 V=447
7: H=64 V=64
8: H=64 V=64
9: H=414 V=415
10: H=414 V=415
11: H=96 V=96
12: H=96 V=96
13: H=382 V=383
14: H=382 V=383
15: H=128 V=128
16: H=128 V=128
17: H=350 V=351
18: H=350 V=351
19: H=160 V=160
20: H=160 V=160
21: H=318 V=319
22: H=318 V=319
23: H=192 V=192
24: H=192 V=192
25: H=286 V=287
26: H=286 V=287
27: H=224 V=224
28: H=224 V=224
29: H=254 V=255
30: H=254 V=255
31: H=256 V=256
32: H=256 V=256
33: H=222 V=223
34: H=222 V=223
35: H=288 V=288
36: H=288 V=288
37: H=190 V=191
38: H=190 V=191
39: H=320 V=320
40: H=320 V=320
41: H=158 V=159
42: H=158 V=159
43: H=352 V=352
44: H=352 V=352
45: H=126 V=127
46: H=126 V=127
47: H=384 V=384
48: H=384 V=384
49: H=94 V=95
50: H=94 V=95
51: H=416 V=416
52: H=416 V=416
53: H=62 V=63
54: H=62 V=63
55: H=448 V=448
56: H=448 V=448
57: H=30 V=31
58: H=30 V=31
59: H=480 V=480
60: H=480 V=480
61: H=510 V=511
62: H=510 V=511
Quote:
It'd also be nice if you could match up some of the signals you've named with node numbers in Visual2C02 so I can add them to nodenames.js
I'm afraid I can overlap you changes. If you send me fresh nodenames.js, I'll update it and send it back. I'm in skype.
org wrote:
I'm calling this thingy: "a twist". Look how these sort of counter work (on H/V example) :
(snip)
I'm not sure exactly what the info in that table means, because the H/V counters themselves count normally from 0 to 340/261 just like any normal counter would - you can see it quite easily in the chip simulator. Whatever the purpose is for the special carry input for bit 5, it seems to be functionally equivalent (from a behavior standpoint) to simply using the carry output from bit 4.
org wrote:
I'm afraid I can overlap you changes. If you send me fresh nodenames.js, I'll update it and send it back. I'm in skype.
I won't be available on Skype for another 6 hours or so (at work right now,
waiting for test scripts to finish running); I just added node names for the sprite H position counters, priority/attribute bits, and pixel shift registers (which are actually inverted), as well as bus lines that feed to the output logic (as well as fixing a few node names to properly indicate whether or not they were inverted).
I don't expect I'll be making many more updates today - feel free to start with what's up there right now and I'll merge in any other changes I make later.
Quietust wrote:
Whatever the purpose is for the special carry input for bit 5, it seems to be functionally equivalent (from a behavior standpoint) to simply using the carry output from bit 4.
Speculation in #nesdev was that this special carry input is there because it reduces gate delay compared to bit 4's carry out.
Finished PPU data reader:
(clickable)
In case you dont need semi-transparent chip background, here is straight circuit :
http://breaknes.com/files/PPU/DATAREAD_gray.jpgNow I have almost whole PPU circuit, only need some time to stitch all pieces together and check missing control lines.
Enjoy
And a last one huge piece of PPU from the middle:
I found, you can use tile horizontal position as palette index in some way.
Look at the bottom of multiplexer, it has additional control line, which I called TH/MUX.
If this line is enabled, MUX using tile horizontal position as palette index, insted of mixed OAM/BG color.
But I haven't found conditions, when this line is enabled yet.
Also I found weird H-counter selector, which selects only each 2,3,5 and 7 lines and output its control lines to OAM FIFO shift registers.
Other parts are already known (OAM index counter, OAM temp memory index counter, OAM evaluation logic and two control registers 2000/2001).
Might the ability to use the horizontal tile position (bits 4-0 of loopy_v) as a palette index be related to the ability to access palette data through $3F00-$3F1F?
Indeed
tepples wrote:
Might the ability to use the horizontal tile position (bits 4-0 of loopy_v) as a palette index be related to the ability to access palette data through $3F00-$3F1F?
org wrote:
Indeed
Technically, it's what causes setting the VRAM address to $3F00-$3FFF to
display the current palette entry on the screen - that "TH/MUX" signal comes from a bit at the very bottom of the chip, where A8-A13 and some other signal are ANDed together (technically /A8 thru /A13 NORed together).
Quote:
comes from a bit at the very bottom of the chip
I forgot about this last tiny piece )
What can you say about weird selector, which is located above MUX ? It feeds H0-H2 counter outputs and fires only each 2,3,5 and 7 H-positions.
I suspect that said "weird selector" is related to the sprite
evaluation or
fetching logic - I don't have as many nodes labeled as you do, so I don't have enough context to know for sure what's going on.
Cleaned-up version of PPU render pipeline:
I identified all blocks and ready to simulate chip on C.
Bonus: /RES pad
EDIT: Reset logic described here
http://breaknes.com/info/9
I fixed some errors and updated render circuit, press F5 in your browser to reload
PPU simulation started here:
http://code.google.com/p/breaks/source/ ... sPPU/PPU.c
H/V random logic details:
Code:
H select: count from 0 to 340 (341 pixels total)
Line 876543210 Decimal Exception Modifier Functional External driver(s) output
0 100010111 279 Front porch latch clear internal
1 100000000 256 Front porch latch set
2 001000001 65 BLNK Start OAM evaluation S/EV
3 X00000XXX 0-7 Object/Background clipping CLIP_O / CLIP_B
4 0XXXXXXXX 0-255 VBL Object/Background clipping CLIP_O / CLIP_B
5 1010100XX 336-339 OAM FIFO clear H.position 0/HPOS
6 000111111 63 OAM evaluation EVAL
7 X11111111 255 End OAM evaluation E/EV
8 000XXXXXX 0-63 Clear secondary OAM I/OAM2
9 100XXXXXX 256-319 BLNK OAM pattern fetch PAR/O
10 0XXXXXXXX 0-255 BLNK / VBL Visible scanline part /VIS
11 XXXXXX00X 0/1 BLNK Name table fetch F/NT
12 XXXXXX11X 6/7 Pattern fetch second byte F/TB
13 XXXXXX10X 4/5 Pattern fetch first byte F/TA
14 1X100XXXX 255-335 BLNK 336-340 weird two name table reads F/-
15 0XXXXXXXX 0-160 BLNK
16 XXXXXX01X 2/3 Attribute table fetch F/AT
17 100001110 270 PICTURE
18 101001000 328
19 100010111 279 Scroll registers update start SC/CNT, SYNC
20 100110000 304 Scroll registers update end
21 101000011 323 Colorburst end BURST
22 100110100 308 Colorburst start
23 101010100 340 V-counter enable
V select: count from 0 to 261 (262 scanlines total)
Line 876543210 Decimal Functional
0 X11110111 247
1 X11110100 244
2 100000101 261
3 X11110001 241
4 X11110001 241
5 000000000 0 Vblank end
6 X11110000 240 Vblank start
7 100000101 261 Visible lines start BLNK
8 100000101 261 Controls RESCL (clear reset flip/flop) RESCL
BLNK is set during vblank period *or* when background *and* sprites are disabled.
VBL is set during vblank period
Also I found odd/even logic (near right to V-select PLA). I updated RENDER.jpg again by recent changes )
Enjoy
BTW: weird selector, which I spotted above MUX is used for object/background clipping.
I completely reversed H/V logic.
Interesting things:
- Pixel count start from H=1, because of pixel #0 is actually rendered, starting from H=329
- PPU starting its work directly from pixel rendering. After displaying all visible pixels front porch appear, followed by back porch.
Back porch itself include hblank period and colorburst:
Table for H values and their meaning:
0: still not clear, looks like a stub. does not appear at very first scanline.
1-256: visible pixels
257-279: front porch
271-328: back porch (overlapped with front porch)
280-304: hblank
309-323: color burst
329-340: start to fetch and render pixel #0
And here is H/V random logic run flow (generated directly by simulation):
Very first line:
H:1 V:0 I/OAM2 F/NT VIS PICTURE
H:2 V:0 I/OAM2 F/NT VIS PICTURE
H:3 V:0 I/OAM2 F/AT VIS PICTURE
H:4 V:0 I/OAM2 F/AT VIS PICTURE
H:5 V:0 I/OAM2 F/TA VIS PICTURE
H:6 V:0 I/OAM2 F/TA VIS PICTURE
H:7 V:0 I/OAM2 F/TB VIS PICTURE
H:8 V:0 I/OAM2 F/TB VIS PICTURE
H:9 V:0 I/OAM2 F/NT VIS PICTURE
H:10 V:0 I/OAM2 F/NT VIS PICTURE
H:11 V:0 I/OAM2 F/AT VIS PICTURE
H:12 V:0 I/OAM2 F/AT VIS PICTURE
H:13 V:0 I/OAM2 F/TA VIS PICTURE
H:14 V:0 I/OAM2 F/TA VIS PICTURE
H:15 V:0 I/OAM2 F/TB VIS PICTURE
H:16 V:0 I/OAM2 F/TB VIS PICTURE
H:17 V:0 I/OAM2 F/NT VIS PICTURE
H:18 V:0 I/OAM2 F/NT VIS PICTURE
H:19 V:0 I/OAM2 F/AT VIS PICTURE
H:20 V:0 I/OAM2 F/AT VIS PICTURE
H:21 V:0 I/OAM2 F/TA VIS PICTURE
H:22 V:0 I/OAM2 F/TA VIS PICTURE
H:23 V:0 I/OAM2 F/TB VIS PICTURE
H:24 V:0 I/OAM2 F/TB VIS PICTURE
H:25 V:0 I/OAM2 F/NT VIS PICTURE
H:26 V:0 I/OAM2 F/NT VIS PICTURE
H:27 V:0 I/OAM2 F/AT VIS PICTURE
H:28 V:0 I/OAM2 F/AT VIS PICTURE
H:29 V:0 I/OAM2 F/TA VIS PICTURE
H:30 V:0 I/OAM2 F/TA VIS PICTURE
H:31 V:0 I/OAM2 F/TB VIS PICTURE
H:32 V:0 I/OAM2 F/TB VIS PICTURE
H:33 V:0 I/OAM2 F/NT VIS PICTURE
H:34 V:0 I/OAM2 F/NT VIS PICTURE
H:35 V:0 I/OAM2 F/AT VIS PICTURE
H:36 V:0 I/OAM2 F/AT VIS PICTURE
H:37 V:0 I/OAM2 F/TA VIS PICTURE
H:38 V:0 I/OAM2 F/TA VIS PICTURE
H:39 V:0 I/OAM2 F/TB VIS PICTURE
H:40 V:0 I/OAM2 F/TB VIS PICTURE
H:41 V:0 I/OAM2 F/NT VIS PICTURE
H:42 V:0 I/OAM2 F/NT VIS PICTURE
H:43 V:0 I/OAM2 F/AT VIS PICTURE
H:44 V:0 I/OAM2 F/AT VIS PICTURE
H:45 V:0 I/OAM2 F/TA VIS PICTURE
H:46 V:0 I/OAM2 F/TA VIS PICTURE
H:47 V:0 I/OAM2 F/TB VIS PICTURE
H:48 V:0 I/OAM2 F/TB VIS PICTURE
H:49 V:0 I/OAM2 F/NT VIS PICTURE
H:50 V:0 I/OAM2 F/NT VIS PICTURE
H:51 V:0 I/OAM2 F/AT VIS PICTURE
H:52 V:0 I/OAM2 F/AT VIS PICTURE
H:53 V:0 I/OAM2 F/TA VIS PICTURE
H:54 V:0 I/OAM2 F/TA VIS PICTURE
H:55 V:0 I/OAM2 F/TB VIS PICTURE
H:56 V:0 I/OAM2 F/TB VIS PICTURE
H:57 V:0 I/OAM2 F/NT VIS PICTURE
H:58 V:0 I/OAM2 F/NT VIS PICTURE
H:59 V:0 I/OAM2 F/AT VIS PICTURE
H:60 V:0 I/OAM2 F/AT VIS PICTURE
H:61 V:0 I/OAM2 F/TA VIS PICTURE
H:62 V:0 I/OAM2 F/TA VIS PICTURE
H:63 V:0 I/OAM2 F/TB VIS PICTURE
H:64 V:0 EVAL I/OAM2 F/TB VIS PICTURE
H:65 V:0 F/NT VIS PICTURE
H:66 V:0 S/EV F/NT VIS PICTURE
H:67 V:0 F/AT VIS PICTURE
H:68 V:0 F/AT VIS PICTURE
H:69 V:0 F/TA VIS PICTURE
H:70 V:0 F/TA VIS PICTURE
H:71 V:0 F/TB VIS PICTURE
H:72 V:0 F/TB VIS PICTURE
H:73 V:0 F/NT VIS PICTURE
H:74 V:0 F/NT VIS PICTURE
H:75 V:0 F/AT VIS PICTURE
H:76 V:0 F/AT VIS PICTURE
H:77 V:0 F/TA VIS PICTURE
H:78 V:0 F/TA VIS PICTURE
H:79 V:0 F/TB VIS PICTURE
H:80 V:0 F/TB VIS PICTURE
H:81 V:0 F/NT VIS PICTURE
H:82 V:0 F/NT VIS PICTURE
H:83 V:0 F/AT VIS PICTURE
H:84 V:0 F/AT VIS PICTURE
H:85 V:0 F/TA VIS PICTURE
H:86 V:0 F/TA VIS PICTURE
H:87 V:0 F/TB VIS PICTURE
H:88 V:0 F/TB VIS PICTURE
H:89 V:0 F/NT VIS PICTURE
H:90 V:0 F/NT VIS PICTURE
H:91 V:0 F/AT VIS PICTURE
H:92 V:0 F/AT VIS PICTURE
H:93 V:0 F/TA VIS PICTURE
H:94 V:0 F/TA VIS PICTURE
H:95 V:0 F/TB VIS PICTURE
H:96 V:0 F/TB VIS PICTURE
H:97 V:0 F/NT VIS PICTURE
H:98 V:0 F/NT VIS PICTURE
H:99 V:0 F/AT VIS PICTURE
H:100 V:0 F/AT VIS PICTURE
H:101 V:0 F/TA VIS PICTURE
H:102 V:0 F/TA VIS PICTURE
H:103 V:0 F/TB VIS PICTURE
H:104 V:0 F/TB VIS PICTURE
H:105 V:0 F/NT VIS PICTURE
H:106 V:0 F/NT VIS PICTURE
H:107 V:0 F/AT VIS PICTURE
H:108 V:0 F/AT VIS PICTURE
H:109 V:0 F/TA VIS PICTURE
H:110 V:0 F/TA VIS PICTURE
H:111 V:0 F/TB VIS PICTURE
H:112 V:0 F/TB VIS PICTURE
H:113 V:0 F/NT VIS PICTURE
H:114 V:0 F/NT VIS PICTURE
H:115 V:0 F/AT VIS PICTURE
H:116 V:0 F/AT VIS PICTURE
H:117 V:0 F/TA VIS PICTURE
H:118 V:0 F/TA VIS PICTURE
H:119 V:0 F/TB VIS PICTURE
H:120 V:0 F/TB VIS PICTURE
H:121 V:0 F/NT VIS PICTURE
H:122 V:0 F/NT VIS PICTURE
H:123 V:0 F/AT VIS PICTURE
H:124 V:0 F/AT VIS PICTURE
H:125 V:0 F/TA VIS PICTURE
H:126 V:0 F/TA VIS PICTURE
H:127 V:0 F/TB VIS PICTURE
H:128 V:0 F/TB VIS PICTURE
H:129 V:0 F/NT VIS PICTURE
H:130 V:0 F/NT VIS PICTURE
H:131 V:0 F/AT VIS PICTURE
H:132 V:0 F/AT VIS PICTURE
H:133 V:0 F/TA VIS PICTURE
H:134 V:0 F/TA VIS PICTURE
H:135 V:0 F/TB VIS PICTURE
H:136 V:0 F/TB VIS PICTURE
H:137 V:0 F/NT VIS PICTURE
H:138 V:0 F/NT VIS PICTURE
H:139 V:0 F/AT VIS PICTURE
H:140 V:0 F/AT VIS PICTURE
H:141 V:0 F/TA VIS PICTURE
H:142 V:0 F/TA VIS PICTURE
H:143 V:0 F/TB VIS PICTURE
H:144 V:0 F/TB VIS PICTURE
H:145 V:0 F/NT VIS PICTURE
H:146 V:0 F/NT VIS PICTURE
H:147 V:0 F/AT VIS PICTURE
H:148 V:0 F/AT VIS PICTURE
H:149 V:0 F/TA VIS PICTURE
H:150 V:0 F/TA VIS PICTURE
H:151 V:0 F/TB VIS PICTURE
H:152 V:0 F/TB VIS PICTURE
H:153 V:0 F/NT VIS PICTURE
H:154 V:0 F/NT VIS PICTURE
H:155 V:0 F/AT VIS PICTURE
H:156 V:0 F/AT VIS PICTURE
H:157 V:0 F/TA VIS PICTURE
H:158 V:0 F/TA VIS PICTURE
H:159 V:0 F/TB VIS PICTURE
H:160 V:0 F/TB VIS PICTURE
H:161 V:0 F/NT VIS PICTURE
H:162 V:0 F/NT VIS PICTURE
H:163 V:0 F/AT VIS PICTURE
H:164 V:0 F/AT VIS PICTURE
H:165 V:0 F/TA VIS PICTURE
H:166 V:0 F/TA VIS PICTURE
H:167 V:0 F/TB VIS PICTURE
H:168 V:0 F/TB VIS PICTURE
H:169 V:0 F/NT VIS PICTURE
H:170 V:0 F/NT VIS PICTURE
H:171 V:0 F/AT VIS PICTURE
H:172 V:0 F/AT VIS PICTURE
H:173 V:0 F/TA VIS PICTURE
H:174 V:0 F/TA VIS PICTURE
H:175 V:0 F/TB VIS PICTURE
H:176 V:0 F/TB VIS PICTURE
H:177 V:0 F/NT VIS PICTURE
H:178 V:0 F/NT VIS PICTURE
H:179 V:0 F/AT VIS PICTURE
H:180 V:0 F/AT VIS PICTURE
H:181 V:0 F/TA VIS PICTURE
H:182 V:0 F/TA VIS PICTURE
H:183 V:0 F/TB VIS PICTURE
H:184 V:0 F/TB VIS PICTURE
H:185 V:0 F/NT VIS PICTURE
H:186 V:0 F/NT VIS PICTURE
H:187 V:0 F/AT VIS PICTURE
H:188 V:0 F/AT VIS PICTURE
H:189 V:0 F/TA VIS PICTURE
H:190 V:0 F/TA VIS PICTURE
H:191 V:0 F/TB VIS PICTURE
H:192 V:0 F/TB VIS PICTURE
H:193 V:0 F/NT VIS PICTURE
H:194 V:0 F/NT VIS PICTURE
H:195 V:0 F/AT VIS PICTURE
H:196 V:0 F/AT VIS PICTURE
H:197 V:0 F/TA VIS PICTURE
H:198 V:0 F/TA VIS PICTURE
H:199 V:0 F/TB VIS PICTURE
H:200 V:0 F/TB VIS PICTURE
H:201 V:0 F/NT VIS PICTURE
H:202 V:0 F/NT VIS PICTURE
H:203 V:0 F/AT VIS PICTURE
H:204 V:0 F/AT VIS PICTURE
H:205 V:0 F/TA VIS PICTURE
H:206 V:0 F/TA VIS PICTURE
H:207 V:0 F/TB VIS PICTURE
H:208 V:0 F/TB VIS PICTURE
H:209 V:0 F/NT VIS PICTURE
H:210 V:0 F/NT VIS PICTURE
H:211 V:0 F/AT VIS PICTURE
H:212 V:0 F/AT VIS PICTURE
H:213 V:0 F/TA VIS PICTURE
H:214 V:0 F/TA VIS PICTURE
H:215 V:0 F/TB VIS PICTURE
H:216 V:0 F/TB VIS PICTURE
H:217 V:0 F/NT VIS PICTURE
H:218 V:0 F/NT VIS PICTURE
H:219 V:0 F/AT VIS PICTURE
H:220 V:0 F/AT VIS PICTURE
H:221 V:0 F/TA VIS PICTURE
H:222 V:0 F/TA VIS PICTURE
H:223 V:0 F/TB VIS PICTURE
H:224 V:0 F/TB VIS PICTURE
H:225 V:0 F/NT VIS PICTURE
H:226 V:0 F/NT VIS PICTURE
H:227 V:0 F/AT VIS PICTURE
H:228 V:0 F/AT VIS PICTURE
H:229 V:0 F/TA VIS PICTURE
H:230 V:0 F/TA VIS PICTURE
H:231 V:0 F/TB VIS PICTURE
H:232 V:0 F/TB VIS PICTURE
H:233 V:0 F/NT VIS PICTURE
H:234 V:0 F/NT VIS PICTURE
H:235 V:0 F/AT VIS PICTURE
H:236 V:0 F/AT VIS PICTURE
H:237 V:0 F/TA VIS PICTURE
H:238 V:0 F/TA VIS PICTURE
H:239 V:0 F/TB VIS PICTURE
H:240 V:0 F/TB VIS PICTURE
H:241 V:0 F/NT VIS PICTURE
H:242 V:0 F/NT VIS PICTURE
H:243 V:0 F/AT VIS PICTURE
H:244 V:0 F/AT VIS PICTURE
H:245 V:0 F/TA VIS PICTURE
H:246 V:0 F/TA VIS PICTURE
H:247 V:0 F/TB VIS PICTURE
H:248 V:0 F/TB VIS PICTURE
H:249 V:0 F/NT VIS PICTURE
H:250 V:0 F/NT VIS PICTURE
H:251 V:0 F/AT VIS PICTURE
H:252 V:0 F/AT VIS PICTURE
H:253 V:0 F/TA VIS PICTURE
H:254 V:0 F/TA VIS PICTURE
H:255 V:0 F/TB VIS PICTURE
H:256 V:0 E/EV EVAL F/TB VIS PICTURE
H:257 V:0 F/NT PAR/O /FO PICTURE SYNC FRPORCH
H:258 V:0 F/NT PAR/O /FO PICTURE SYNC FRPORCH
H:259 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:260 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:261 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:262 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:263 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:264 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:265 V:0 F/NT PAR/O /FO PICTURE SYNC FRPORCH
H:266 V:0 F/NT PAR/O /FO PICTURE SYNC FRPORCH
H:267 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:268 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:269 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:270 V:0 PAR/O /FO PICTURE SYNC FRPORCH
H:271 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:272 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:273 V:0 F/NT PAR/O /FO SYNC FRPORCH BKPORCH
H:274 V:0 F/NT PAR/O /FO SYNC FRPORCH BKPORCH
H:275 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:276 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:277 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:278 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:279 V:0 PAR/O /FO SYNC FRPORCH BKPORCH
H:280 V:0 SC/CNT PAR/O /FO BKPORCH
H:281 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:282 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:283 V:0 SC/CNT PAR/O /FO BKPORCH
H:284 V:0 SC/CNT PAR/O /FO BKPORCH
H:285 V:0 SC/CNT PAR/O /FO BKPORCH
H:286 V:0 SC/CNT PAR/O /FO BKPORCH
H:287 V:0 SC/CNT PAR/O /FO BKPORCH
H:288 V:0 SC/CNT PAR/O /FO BKPORCH
H:289 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:290 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:291 V:0 SC/CNT PAR/O /FO BKPORCH
H:292 V:0 SC/CNT PAR/O /FO BKPORCH
H:293 V:0 SC/CNT PAR/O /FO BKPORCH
H:294 V:0 SC/CNT PAR/O /FO BKPORCH
H:295 V:0 SC/CNT PAR/O /FO BKPORCH
H:296 V:0 SC/CNT PAR/O /FO BKPORCH
H:297 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:298 V:0 SC/CNT F/NT PAR/O /FO BKPORCH
H:299 V:0 SC/CNT PAR/O /FO BKPORCH
H:300 V:0 SC/CNT PAR/O /FO BKPORCH
H:301 V:0 SC/CNT PAR/O /FO BKPORCH
H:302 V:0 SC/CNT PAR/O /FO BKPORCH
H:303 V:0 SC/CNT PAR/O /FO BKPORCH
H:304 V:0 SC/CNT PAR/O /FO BKPORCH
H:305 V:0 F/NT PAR/O /FO BKPORCH
H:306 V:0 F/NT PAR/O /FO BKPORCH
H:307 V:0 PAR/O /FO BKPORCH
H:308 V:0 PAR/O /FO BKPORCH
H:309 V:0 PAR/O /FO BKPORCH BURST
H:310 V:0 PAR/O /FO BKPORCH BURST
H:311 V:0 PAR/O /FO BKPORCH BURST
H:312 V:0 PAR/O /FO BKPORCH BURST
H:313 V:0 F/NT PAR/O /FO BKPORCH BURST
H:314 V:0 F/NT PAR/O /FO BKPORCH BURST
H:315 V:0 PAR/O /FO BKPORCH BURST
H:316 V:0 PAR/O /FO BKPORCH BURST
H:317 V:0 PAR/O /FO BKPORCH BURST
H:318 V:0 PAR/O /FO BKPORCH BURST
H:319 V:0 PAR/O /FO BKPORCH BURST
H:320 V:0 PAR/O /FO BKPORCH BURST
H:321 V:0 F/NT BKPORCH BURST
H:322 V:0 F/NT BKPORCH BURST
H:323 V:0 F/AT BKPORCH BURST
H:324 V:0 F/AT BKPORCH
H:325 V:0 F/TA BKPORCH
H:326 V:0 F/TA BKPORCH
H:327 V:0 F/TB BKPORCH
H:328 V:0 F/TB BKPORCH
H:329 V:0 F/NT PICTURE
H:330 V:0 F/NT PICTURE
H:331 V:0 F/AT PICTURE
H:332 V:0 F/AT PICTURE
H:333 V:0 F/TA PICTURE
H:334 V:0 F/TA PICTURE
H:335 V:0 F/TB PICTURE
H:336 V:0 F/TB PICTURE
H:337 V:0 0/HPOS EVAL F/NT /FO PICTURE
H:338 V:0 0/HPOS EVAL F/NT /FO PICTURE
H:339 V:0 0/HPOS EVAL /FO PICTURE
H:340 V:0 0/HPOS EVAL /FO PICTUREAll other lines start from this:
H:0 V:1 /FO PICTURE
H:1 V:1 I/OAM2 F/NT VIS PICTURE
H:2 V:1 I/OAM2 F/NT VIS PICTURE
.... and so on
Complete list of all H/V commands:
CLIP_O, CLIP_B: clip objects/background
0/HPOS: reset OAM FIFO H.position counters
EVAL: sprite evaluation in progress
PAR/O: fetch sprite patterns
VIS: visible scanline part (excluding fron porch)
BLNK: picture not seen (vblank) or disabled by control regs
RESCL: clear reset flip/flop
S/EV, E/EV: start/end OAM evaluation
I/OAM2: init secondary OAM
SC/CNT: update scroll registers. issued right after hblank.
F/NT, F/AT, F/TA, F/TB, /FO: memory fetch controls. NT - name table, AT - attribute table, TA - tile #0, TB - tile #1, /FO - active during sprite pattern fetch
PICTURE, BURST, SYNC : videout controls
/BPORCH :back porch (internal)
/FPORCH :front porch (internal)
/INT: /INT pad (VBlank interupt)
Source code of H/V simulation available here:
http://code.google.com/p/breaks/source/ ... sPPU/PPU.chttp://code.google.com/p/breaks/source/ ... sPPU/PPU.h
Sequence for "blank" picture (when rendering disabled or vblank occure):
H:0 V:1 /FO BLNK PICTURE
H:1 V:1 I/OAM2 /FO BLNK PICTURE
...
H:63 V:1 I/OAM2 /FO BLNK PICTURE
H:64 V:1 EVAL I/OAM2 /FO BLNK PICTURE
H:65 V:1 /FO BLNK PICTURE
...
H:255 V:1 /FO BLNK PICTURE
H:256 V:1 E/EV EVAL /FO BLNK PICTURE
H:257 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:258 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:259 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:260 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:261 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:262 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:263 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:264 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:265 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:266 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:267 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:268 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:269 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:270 V:1 /FO BLNK PICTURE SYNC FRPORCH
H:271 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:272 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:273 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:274 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:275 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:276 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:277 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:278 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:279 V:1 /FO BLNK SYNC FRPORCH BKPORCH
H:280 V:1 /FO BLNK BKPORCH
H:281 V:1 /FO BLNK BKPORCH
H:282 V:1 /FO BLNK BKPORCH
H:283 V:1 /FO BLNK BKPORCH
H:284 V:1 /FO BLNK BKPORCH
H:285 V:1 /FO BLNK BKPORCH
H:286 V:1 /FO BLNK BKPORCH
H:287 V:1 /FO BLNK BKPORCH
H:288 V:1 /FO BLNK BKPORCH
H:289 V:1 /FO BLNK BKPORCH
H:290 V:1 /FO BLNK BKPORCH
H:291 V:1 /FO BLNK BKPORCH
H:292 V:1 /FO BLNK BKPORCH
H:293 V:1 /FO BLNK BKPORCH
H:294 V:1 /FO BLNK BKPORCH
H:295 V:1 /FO BLNK BKPORCH
H:296 V:1 /FO BLNK BKPORCH
H:297 V:1 /FO BLNK BKPORCH
H:298 V:1 /FO BLNK BKPORCH
H:299 V:1 /FO BLNK BKPORCH
H:300 V:1 /FO BLNK BKPORCH
H:301 V:1 /FO BLNK BKPORCH
H:302 V:1 /FO BLNK BKPORCH
H:303 V:1 /FO BLNK BKPORCH
H:304 V:1 /FO BLNK BKPORCH
H:305 V:1 /FO BLNK BKPORCH
H:306 V:1 /FO BLNK BKPORCH
H:307 V:1 /FO BLNK BKPORCH
H:308 V:1 /FO BLNK BKPORCH
H:309 V:1 /FO BLNK BKPORCH BURST
H:310 V:1 /FO BLNK BKPORCH BURST
H:311 V:1 /FO BLNK BKPORCH BURST
H:312 V:1 /FO BLNK BKPORCH BURST
H:313 V:1 /FO BLNK BKPORCH BURST
H:314 V:1 /FO BLNK BKPORCH BURST
H:315 V:1 /FO BLNK BKPORCH BURST
H:316 V:1 /FO BLNK BKPORCH BURST
H:317 V:1 /FO BLNK BKPORCH BURST
H:318 V:1 /FO BLNK BKPORCH BURST
H:319 V:1 /FO BLNK BKPORCH BURST
H:320 V:1 /FO BLNK BKPORCH BURST
H:321 V:1 /FO BLNK BKPORCH BURST
H:322 V:1 /FO BLNK BKPORCH BURST
H:323 V:1 /FO BLNK BKPORCH BURST
H:324 V:1 /FO BLNK BKPORCH
H:325 V:1 /FO BLNK BKPORCH
H:326 V:1 /FO BLNK BKPORCH
H:327 V:1 /FO BLNK BKPORCH
H:328 V:1 /FO BLNK BKPORCH
H:329 V:1 /FO BLNK PICTURE
H:330 V:1 /FO BLNK PICTURE
H:331 V:1 /FO BLNK PICTURE
H:332 V:1 /FO BLNK PICTURE
H:333 V:1 /FO BLNK PICTURE
H:334 V:1 /FO BLNK PICTURE
H:335 V:1 /FO BLNK PICTURE
H:336 V:1 /FO BLNK PICTURE
H:337 V:1 0/HPOS EVAL /FO BLNK PICTURE
H:338 V:1 0/HPOS EVAL /FO BLNK PICTURE
H:339 V:1 0/HPOS EVAL /FO BLNK PICTURE
H:340 V:1 0/HPOS EVAL /FO BLNK PICTURE
"0: still not clear, looks like a stub. does not appear at very first scanline."
Dot 0 being skipped on the first line could be the "missing dot on pre-render x=340 every other frame", used to realign pixel boundaries relative to the color burst.
Something epic today
Complete PPU circuit:
(clickable)
Although some control lines are yet not unknown (their meaning will discover as soon as I simulate it), transistor interconnections are done.
I wish I could understand these images as well as some of you guys do... I'm really glad you're making progress, though!
Any findings on how writes to the PPU registers work? I am currently tearing my hair out (or well, really just a previously loosened dreadlock TBH) about it in
this experiment