Eccentric pedantic "monochrome" glitch
Moderator: Moderators
Eccentric pedantic "monochrome" glitch
In this post, I observed that it should be possible to get the wrong value of pal_mono stuck inside the palette hardware on certain CPU-PPU phases. And... lo and behold, I have a test ROM that shows it, by writing #0 to $2101 repeatedly:
Now, what's specifically interesting about this is: no matter how many times I reset or power cycle the NES, I only ever see black, or this specific shade of blue. So we might finally have a robust way of detecting at least one CPU-PPU subpixel phase. (So please other people help verify!)
This specific timing is: M2 goes high before the data bus has been driven, so pal_mono temporarily gets the value from open bus. Because the output of pal_mono isn't gated, the palette lookup initially zeroes the lower four bits of the result from the palette RAM, and then an edge between pixels captures this wrong value for that one pixel.
This specific timing is: M2 goes high before the data bus has been driven, so pal_mono temporarily gets the value from open bus. Because the output of pal_mono isn't gated, the palette lookup initially zeroes the lower four bits of the result from the palette RAM, and then an edge between pixels captures this wrong value for that one pixel.
- Attachments
-
- catcmono.7z
- nes, bin, asm inside
- (763 Bytes) Downloaded 174 times
Re: Eccentric pedantic "monochrome" glitch
Wonderful, thanks for this test!
You say shade of blue, but these should be white dots, right?
Kitrinx identified that greyscale, emphasis 2, slave mode, and NMI enable are all implemented in this same way. I think this might explain the issue with Hi-Def NES and NESRGB mentioned here and seen here where writes to $2000 can corrupt the EXT data output for a dot. If $20 is being seen as the write value for a dot, that would kick the PPU out of slave mode and cause this. If this is indeed fixed in the rev H PPU as mentioned on that page, perhaps the other bits are, too?
Would this also mean that writes to $2000 when NMI would trigger could prevent NMI by briefly disabling it?
You say shade of blue, but these should be white dots, right?
Kitrinx identified that greyscale, emphasis 2, slave mode, and NMI enable are all implemented in this same way. I think this might explain the issue with Hi-Def NES and NESRGB mentioned here and seen here where writes to $2000 can corrupt the EXT data output for a dot. If $20 is being seen as the write value for a dot, that would kick the PPU out of slave mode and cause this. If this is indeed fixed in the rev H PPU as mentioned on that page, perhaps the other bits are, too?
Would this also mean that writes to $2000 when NMI would trigger could prevent NMI by briefly disabling it?
Re: Eccentric pedantic "monochrome" glitch
NES pixels are two-thirds of a color subcarrier period wide. A white dot that small will carry a small amount of color fringe depending on its relationship to the color burst phase.
Re: Eccentric pedantic "monochrome" glitch
Naively, if I were writing an implementation of NESRGB, I'd replace the data bus as soon as I knew what address it was. I wouldn't wait for the actual contents of the data bus before deciding to replace it. So ... I don't think that's what's going on here?Fiskbit wrote: ↑Fri Sep 18, 2020 7:05 am Kitrinx identified that greyscale, emphasis 2, slave mode, and NMI enable are all implemented in this same way. I think this might explain the issue with Hi-Def NES and NESRGB mentioned here and seen here where writes to $2000 can corrupt the EXT data output for a dot. If $20 is being seen as the write value for a dot, that would kick the PPU out of slave mode and cause this.
I did try to write the same test to get the "sparkle" I mentioned on emph2 to show up, but I didn't see it. But I might not have actually gotten my NES to boot my ROM :p
As tepples says.You say shade of blue, but these should be white dots, right?
Because the CPU clock and the colorburst clock are forever linked after boot, the color should be fixed. But rainwarrior separately identified that at least on his NES, he's seen all six different colorburst-to-pixel clock phases. I have no idea how that works such that you'd get a 50ns difference in release from reset for different subsystems inside the PPU, but I can't argue with his results.
Now that I've had a chance to sleep, I think that this test should capture two different subpixel alignments, because the data bus is driven roughly 100ns after M2 rises.
Don't see why not. Slightly more clever metal layout should have left enough space for these bits to be implemented correctly.If this is indeed fixed in the rev H PPU as mentioned on that page, perhaps the other bits are, too?
They even have the synchronized copies of these signals already generated. The subsequent logic just connects to the output of the latch instead of these synchronized copies.
slave_mode → 6245
pal_mono → 6243
emph2 → 6239
That said, enable_nmi is a little weird: there's no space for the gate to synchronize it. There's a bend in /write_2000_reg right over top that means there's no space for the polysilicon to make the transmission gate.
Delay NMI or cause reentry, not prevent it. Only reads from $2002, or scanline 20, clear the S-R latch.Would this also mean that writes to $2000 when NMI would trigger could prevent NMI by briefly disabling it?
Re: Eccentric pedantic "monochrome" glitch
I believe I've confirmed the emph2 case with the attached test ROM on a rev G frontloader. I manually hacked this one together in a hex editor from your binary, so no source for this. It writes #$81 to $2101 rapidly. On affected alignments, this will trigger white dots.
- Attachments
-
- emph2_sparkle_test.nes
- (32.02 KiB) Downloaded 158 times
Re: Eccentric pedantic "monochrome" glitch
... That's almost exactly the same test that I wrote but I never saw the white dots from emph2 being temporarily disabled.
...ohhhh...
if my first "catcmono" test always produces blue-tinted dots, then the sparkle will always happen at the wrong moment relative to colorburst phase... somehow I have to get a different CPU-to-colorburst alignment to get that to show up.
...ohhhh...
if my first "catcmono" test always produces blue-tinted dots, then the sparkle will always happen at the wrong moment relative to colorburst phase... somehow I have to get a different CPU-to-colorburst alignment to get that to show up.
Re: Eccentric pedantic "monochrome" glitch
I've written a variation on the test that tries to tickle both the "catch the monochrome bit for one pixel" and the "blue emphasis is entirely asynchronous" at the same time.
I've tested it with PPU /RESET tied to CPU /RESET, and with PPU /RESET floating.
The code uses the CPU to draw this parallelogram: Legend:
Red: places where we try to glitch pal_mono on for one pixel
Yellow-green: places where we turn pal_mono on
Seagreen: places where we try to glitch pal_mono off for one pixel
Purple: places where we turn pal_mono off
At all four of the above, we also try to temporarily disable blue emphasis. Previous estimates for 2A03 bus timing have this at around 100ns, or about half a pixel, or roughly the same width as a SNES 512px pixel.
Blue: places where pal_mono remains on
I've gotten a bunch of different results depending on exact phases.
Results with PPU /RESET floating:
pal_mono glitch dots can be any color - here it's yellow but I have seen red, green, blue-or-cyan, and magenta also: emph2 sparkle is often visible: How often should emph2 sparkle be visible? Well, the relevant node inside the 2C02 (195, "chroma_ring3") is high for 3MCy and low for 3MCy. The open bus value should be driven for roughly 2MCy, but the relative phase is unknown. So we should see multiple different levels of severity of the emph2 sparkle depending on exact phase between the two, including factors like "how many ns does it take for the signal to get out of the 2A03 and into the 2C02". But I'd expect sparkle visible in 2/3 or 5/6 of the possible phase differences.
With PPU /RESET tied to CPU /RESET:
pal_mono is almost always blue (or cyan?)
emph2 sparkle is never visible: Bewilderingly: the 2A03's internal clock divider is not reset by asserting the CPU's /RESET, but the 2C02's colorburst sequencer is. So how on earth was I not getting differing chroma-to-CPU phases when the PPU should have had its phase changed every time I pressed the reset button?
I've tested it with PPU /RESET tied to CPU /RESET, and with PPU /RESET floating.
The code uses the CPU to draw this parallelogram: Legend:
Red: places where we try to glitch pal_mono on for one pixel
Yellow-green: places where we turn pal_mono on
Seagreen: places where we try to glitch pal_mono off for one pixel
Purple: places where we turn pal_mono off
At all four of the above, we also try to temporarily disable blue emphasis. Previous estimates for 2A03 bus timing have this at around 100ns, or about half a pixel, or roughly the same width as a SNES 512px pixel.
Blue: places where pal_mono remains on
I've gotten a bunch of different results depending on exact phases.
Results with PPU /RESET floating:
pal_mono glitch dots can be any color - here it's yellow but I have seen red, green, blue-or-cyan, and magenta also: emph2 sparkle is often visible: How often should emph2 sparkle be visible? Well, the relevant node inside the 2C02 (195, "chroma_ring3") is high for 3MCy and low for 3MCy. The open bus value should be driven for roughly 2MCy, but the relative phase is unknown. So we should see multiple different levels of severity of the emph2 sparkle depending on exact phase between the two, including factors like "how many ns does it take for the signal to get out of the 2A03 and into the 2C02". But I'd expect sparkle visible in 2/3 or 5/6 of the possible phase differences.
With PPU /RESET tied to CPU /RESET:
pal_mono is almost always blue (or cyan?)
emph2 sparkle is never visible: Bewilderingly: the 2A03's internal clock divider is not reset by asserting the CPU's /RESET, but the 2C02's colorburst sequencer is. So how on earth was I not getting differing chroma-to-CPU phases when the PPU should have had its phase changed every time I pressed the reset button?
- Attachments
-
- blueemp2.7z
- source, binary, nes file included
- (972 Bytes) Downloaded 161 times
Re: Eccentric pedantic "monochrome" glitch
I've since taken my oscilloscope and checked the original test, and I think it's only ever capturing one subpixel alignment.
No matter how many times I power cycle my NES, I only ever see the dot due to a glitched value of pal_mono at this position (from roughly the 90ns before R/W rises to roughly 50ns after).
From my previous measurement, this should be roughly 330ns, or 1.75 pixels, after the /PPUCE for the write is asserted. Looking in visual2c02 I see a direct explanation for 1.5 of them, so ... that last 1/4 pixel must be the requisite phase alignment.
- Attachments
-
- mIMG_3078.png (4.48 KiB) Viewed 7974 times
Re: Eccentric pedantic "monochrome" glitch
I spent a few minutes looking at siliconpr0n's decapped 2C04, and found that all of these asynchronous behaviors are there, too:
emph2 (blue) -
https://siliconpr0n.org/map/nintendo/rp ... y=2707&z=6
pal_mono
https://siliconpr0n.org/map/nintendo/rp ... y=2655&z=6
slave_mode exists at all
https://siliconpr0n.org/map/nintendo/rp ... y=2669&z=6
but is cut off from any further hardware:
https://siliconpr0n.org/map/nintendo/rp ... y=2668&z=6
Palette reads don't exist, so the logic implementing pal_mono is a little simpler:
https://siliconpr0n.org/map/nintendo/rp ... y=3049&z=6
compare visual2c02 node 10679
The 2A03letterless has a longer M2 duty cycle, so the duration during which a bad value of emph2 or pal_mono can leak out should be longer, and it should be easier to tickle these various glitches on Vs. Systems or older Famicoms.
(Also: does anyone have a 2A03letterless and can test what the actual duty cycle of M2 is? It's not 3/4.)
—
I've measured the actual amount of time that /PPUCE goes low before the NES drives the data bus—80ns, or about 1.7 master clock cycles. For reasons I'm not clear (does emphasis change the supply voltage to the video DAC?), it takes a comparatively huge amount of time for emph2 to percolate through the 2C02, somewhere around 100-120ns: This latter test was done by overriding the PPU's master clock with a 7MHz source so that we can see the effect of emphasis without having to manually step through all the different video phases.
I've also got a set of photos of all six CPU-to-colorburst alignments, but it'll take me a little while to stitch them into something suitable for presentation.
emph2 (blue) -
https://siliconpr0n.org/map/nintendo/rp ... y=2707&z=6
pal_mono
https://siliconpr0n.org/map/nintendo/rp ... y=2655&z=6
slave_mode exists at all
https://siliconpr0n.org/map/nintendo/rp ... y=2669&z=6
but is cut off from any further hardware:
https://siliconpr0n.org/map/nintendo/rp ... y=2668&z=6
Palette reads don't exist, so the logic implementing pal_mono is a little simpler:
https://siliconpr0n.org/map/nintendo/rp ... y=3049&z=6
compare visual2c02 node 10679
The 2A03letterless has a longer M2 duty cycle, so the duration during which a bad value of emph2 or pal_mono can leak out should be longer, and it should be easier to tickle these various glitches on Vs. Systems or older Famicoms.
(Also: does anyone have a 2A03letterless and can test what the actual duty cycle of M2 is? It's not 3/4.)
—
I've measured the actual amount of time that /PPUCE goes low before the NES drives the data bus—80ns, or about 1.7 master clock cycles. For reasons I'm not clear (does emphasis change the supply voltage to the video DAC?), it takes a comparatively huge amount of time for emph2 to percolate through the 2C02, somewhere around 100-120ns: This latter test was done by overriding the PPU's master clock with a 7MHz source so that we can see the effect of emphasis without having to manually step through all the different video phases.
I've also got a set of photos of all six CPU-to-colorburst alignments, but it'll take me a little while to stitch them into something suitable for presentation.
Re: Eccentric pedantic "monochrome" glitch
And with this post, I think I've finished exploring the ideas.
To coax this effect out, I used blue emphasis on top of solid color #$08. Together, this works out to a color that should just be black in the US (7 IRE), and any moment that emphasis is turned off should be very conspicuous.
Here's the photos of the six (2A03-vs-2C02) alignments between CPU phase and colorburst phase. Four of the six phases are really unambiguously different; the last two (top left and top center) are pretty hard to tell apart. The darker phases are underexposed (and fixed after the fact) because I put the oscilloscope in the same exposure as the TV.
Unfortunately, colorburst phase is almost entirely decoupled from pixel clock phase, so this is basically useless from a diagnostic point of view.
All of the emph2 tests require the NES's normal open bus behavior; it won't work with a PowerPak and may not work on any NoaCs. I did test an earlier version of this with the UA6528 (date code 9114) that zoinknoise sent me, and got similar (but slightly darker) results. (The earlier "catcmono" test should work on a PowerPak: there it should glitch D0 high before the CPU drives the pin low, the same as we fake by writing to $2101)
In the attached picture, the six TV photos correspond to the oscilloscope photo that's immediately above or below them. The TV photos are relatively tight crops of only 50ish scanlines. The oscilloscope traces are always CPU D7 (on top) and PPU pin 21 (on bottom)
To coax this effect out, I used blue emphasis on top of solid color #$08. Together, this works out to a color that should just be black in the US (7 IRE), and any moment that emphasis is turned off should be very conspicuous.
Here's the photos of the six (2A03-vs-2C02) alignments between CPU phase and colorburst phase. Four of the six phases are really unambiguously different; the last two (top left and top center) are pretty hard to tell apart. The darker phases are underexposed (and fixed after the fact) because I put the oscilloscope in the same exposure as the TV.
Unfortunately, colorburst phase is almost entirely decoupled from pixel clock phase, so this is basically useless from a diagnostic point of view.
All of the emph2 tests require the NES's normal open bus behavior; it won't work with a PowerPak and may not work on any NoaCs. I did test an earlier version of this with the UA6528 (date code 9114) that zoinknoise sent me, and got similar (but slightly darker) results. (The earlier "catcmono" test should work on a PowerPak: there it should glitch D0 high before the CPU drives the pin low, the same as we fake by writing to $2101)
In the attached picture, the six TV photos correspond to the oscilloscope photo that's immediately above or below them. The TV photos are relatively tight crops of only 50ish scanlines. The oscilloscope traces are always CPU D7 (on top) and PPU pin 21 (on bottom)
- Attachments
-
- blueemp3.7z
- (837 Bytes) Downloaded 147 times
- Jarhmander
- Formerly ~J-@D!~
- Posts: 568
- Joined: Sun Mar 12, 2006 12:36 am
- Location: Rive nord de Montréal
Re: Eccentric pedantic "monochrome" glitch
Long ago, I took that measure and yes, it's ¾. Not the best measurements in the world, but it can clearly be seen.
((λ (x) (x x)) (λ (x) (x x)))
Re: Eccentric pedantic "monochrome" glitch
Looks to me like it's actually 17/24.
The reason I say it can't be simply 3/4 is because the decapped letterless 2A03 shows the same "two twisted-ring counters ORed together" that the the decapped 2A03G (look around node 13923) does, so the duty cycle has to be (some odd number)÷24
Nonetheless, thanks for reminding me of that old post! It predated my making the page where I've tried to compile all of this.
The reason I say it can't be simply 3/4 is because the decapped letterless 2A03 shows the same "two twisted-ring counters ORed together" that the the decapped 2A03G (look around node 13923) does, so the duty cycle has to be (some odd number)÷24
Nonetheless, thanks for reminding me of that old post! It predated my making the page where I've tried to compile all of this.
- Jarhmander
- Formerly ~J-@D!~
- Posts: 568
- Joined: Sun Mar 12, 2006 12:36 am
- Location: Rive nord de Montréal
Re: Eccentric pedantic "monochrome" glitch
Huh? How it can be 17/24? I count 6 falling edges when M2 falls. And M2 changes *only* on falling edges of the master clock... For the duty cycle to be 17/24, M2 would have to change state on a raising and falling edges, wouldn't it?
And sadly, I can't decipher die photographs (yet?), so I can't see what you are mentioning.
But, glad to help nonetheless!
And sadly, I can't decipher die photographs (yet?), so I can't see what you are mentioning.
But, glad to help nonetheless!
((λ (x) (x x)) (λ (x) (x x)))
Re: Eccentric pedantic "monochrome" glitch
... No, you're right. Drat.Jarhmander wrote: ↑Thu Oct 01, 2020 6:32 pm Huh? How it can be 17/24? I count 6 falling edges when M2 falls. And M2 changes *only* on falling edges of the master clock... For the duty cycle to be 17/24, M2 would have to change state on a raising and falling edges, wouldn't it?
I thought I'd stack up the 2A03 and 2A03G input dividers for a visual comparison, and ... now I see that the 2A03's input divider is significantly smaller. It still has the same OR gate that combines φ0 with some other phase, but that'd be necessary even for 3/4 duty.And sadly, I can't decipher die photographs (yet?), so I can't see what you are mentioning.
Re: Eccentric pedantic "monochrome" glitch
I just spent a bit of time tracing layer images for the clock divider - when I get a chance tomorrow, I'll vectorize them and throw them into ChipSim (like I did with that other "mystery logic" on the revisionless 2A03) so we can clearly see what's going on.
Edit: it's done, and a quick round of simulating yielded the following timings:
This confirms that the duty cycle is, indeed, 17/24.
Edit: it's done, and a quick round of simulating yielded the following timings:
Code: Select all
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 - Master CLK in
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 - CPU CLK In
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 - M2 Output Modifier
And that's exactly what it does, and the same is true of the RP2A03G (which has a 15/24 duty cycle) - the 6502's clock input changes on rising input clock edges, but the "early-M2" logic triggers on falling input clock edges.Jarhmander wrote: ↑Thu Oct 01, 2020 6:32 pm Huh? How it can be 17/24? I count 6 falling edges when M2 falls. And M2 changes *only* on falling edges of the master clock... For the duty cycle to be 17/24, M2 would have to change state on a raising and falling edges, wouldn't it?
The 2A03G's clock divider is larger because it contains unused circuitry from the 2A07's /16 divider.
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.