FamiCom CrossFire-an NES with two PPUs

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

I get it. However, can the CPU tell the PPU to skip one pixel (for example, by writing to a register)? I don't remember reading about that in the PPU's programming reference.
Also, I believe that having a way to force the PPUs into sync no matter how far they have drifted away from each other is simpler than figuring out the difference in phase and adjusting pixel-by-pixel.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: FamiCom CrossFire-an NES with two PPUs

Post by lidnariq »

No, the only knob is "have rendering on at the end of the pre-rendering scanline", in which case the NTSC PPU will skip one pixel every other vblank. If the CPU wants to prevent that while still drawing, it has to use raster effects to turn on rendering late. And if it wants to keep drawing on one PPU while it does bulk updates to the other, the raster effect becomes mandatory.

The problem with resetting the PPUs to sync them is that they won't listen to anything for roughly 1.5 redraws afterwards. It's a very heavy-handed solution to something that would appreciate a lighter touch.

There's a "Open Hardware" pixel skipper that was designed for use with the SNES, but it works to fix the 2C02's missing pixel also: https://github.com/marqs85/snes_dejitter
Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

The missing pixel is a worse problem than i ever imageined... The SNES pixel skipper needs a CPLD, but I knid of want to implement everything using chips from the 80s. (If something has to be done in FPGA or CPLD, I'll use one)
lidnariq wrote: Tue Apr 05, 2022 12:36 am The problem with resetting the PPUs to sync them is that they won't listen to anything for roughly 1.5 redraws afterwards.
That's not a huge problem, if the rendering is not disabled during that period. Turning on/off PPU usually happens during loading, so a little more delay is hardly noticable. However, if the screen is blanked for several frames, it's another story. The programmer needs to implement some sort of fade in/fade out effect to hide the blanked frames.
Another idea is to just disable sprites on the 'disabled' PPU and set all tiles to empty, or disable the background and move all sprites off-screen. An even easier solution is set all entries in the register connecting the EXT pins to zero. This will essentially disable the secondary PPU without disable rendering
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Fiskbit »

Rendering is disabled during the init period after PPU reset ($2001 forced to 0), though perhaps it might still show input from the EXT pins. https://www.nesdev.org/wiki/PPU_power_up_state
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: FamiCom CrossFire-an NES with two PPUs

Post by Ben Boldt »

Andy18650 wrote: Fri Apr 08, 2022 8:59 am The missing pixel is a worse problem than i ever imageined... The SNES pixel skipper needs a CPLD, but I knid of want to implement everything using chips from the 80s. (If something has to be done in FPGA or CPLD, I'll use one)
I don't know anything about this but something simple enough to be done with a CPLD can likely be done with a bunch of 1970s/80s discrete logic chips and a large circuit board. Given the wide choices of gates, flop-flops, multiplexers, etc, it should be quite realistic and doable. The challenge would be optimizing chip count and making the whole thing small enough to fit into the case.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: FamiCom CrossFire-an NES with two PPUs

Post by lidnariq »

You can probably get away with a pass transistor - you only need to turn it off for 4 master clocks once every 700 thousand or so.
Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

lidnariq wrote: Fri Apr 08, 2022 5:19 pm You can probably get away with a pass transistor - you only need to turn it off for 4 master clocks once every 700 thousand or so.
700 thousand... that sounds like a big counter (and a big decoder to get to the exact number). A rough estimate is 4 74LS393s, a bunch of not gate and 2 74LS30 connected together by a or gate. This is not ideal... But the other option is letting the screen to flash for one or two frame (since both PPUs are set as input, the screen must be blank).
I kind of understand why this topic has been brought up several times over the years without ever coming close to reailzation. The missing dot is just... annoying. Is it a mistake made by Ricoh or it's an intentional design? If it's the latter, why? I'm not giving up though, not yet.
By the way, I want most programs written for FCCF to run on both PAL and NTSC machines without any specific code for each format, perferrably not even a 'if PAL' branch. That's another reason why I prefer 'reset both PPU' over 'clock-gate the missing pixel'.
Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

One question unrelated to the missing dot problem: does any game use the on-board memory shadowing? If not, I can save a few gates for legacy compatibility.
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: FamiCom CrossFire-an NES with two PPUs

Post by Ben Boldt »

Is this as simple as counting to 700,000? That takes 20 counter bits. You can use presettable counters and set the preset values for a specific count. Then trigger on the overflow output, which would also reset the counters. You can use up or down counters and do the math to the preset value accordingly. If you need to hold for X cycles after triggering, there are cool tricks to do that too, just a little more complicated.

I have these 74HC4060 chips that are 14-bit counters. They are not presettable and output only the highest order bits. There is probably a way to use one of those to chew up large portions of the counting. For example, make a state machine that runs through that entire chip X times, then Y more counts after that, then trigger. You get to try all sorts of crazy ideas like this, then compare at the end how many chips each solution uses to find the best one.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: FamiCom CrossFire-an NES with two PPUs

Post by lidnariq »

Andy18650 wrote: Sat Apr 09, 2022 9:06 am 700 thousand... that sounds like a big counter (and a big decoder to get to the exact number). A rough estimate is 4 74LS393s, a bunch of not gate and 2 74LS30 connected together by a or gate. This is not ideal... But the other option is letting the screen to flash for one or two frame (since both PPUs are set as input, the screen must be blank).
I mean, you don't need to just count to 341×262×2×4 - you need to check if each PPU needs the extra 4 clocks inserted. Previous implementations have used an hsync detector and insert one extra pixel if hsync is too early.

It occurs to me we could also detect ALE being asserted on two adjacent pixels (2MClk on, 2MClk off, 2MClk on - note that I've only measured a 2C02G and we suspect earlier PPUs are different) and insert 4 extra clocks (starve the 2C02 of extra clocks) then instead. wait, this is the exact opposite of when an extra pixel needs to be inserted
Is it a mistake made by Ricoh or it's an intentional design? If it's the latter, why?
Intentional, but a workaround for a different flaw. The desire was to prevent the screen from flickering at 20Hz, which is what normally happens because 341×262×4÷6 is 59561 + 1/3 NTSC chroma cycles per redraw, which means that luma-chroma crosstalk patterns would happen slower. By alternating between full length, and one pixel too short (2/3 of a NTSC chroma cycle), they achieve 30Hz flicker instead.

The "right" solution would have been for the NTSC PPU to have drawn 341.25 pixels per scanline, so that there were exactly 227.5 chroma periods per scanline, and 263 scanlines, so that there were exactly 59832.5 NTSC chroma cycles per redraw, and the 30Hz flicker would have been stable. (Indeed, the VIC-20 and C64 do this)

PAL-B PPUs instead generate 341×312×5÷6 = 88660 PAL chroma cycles per redraw, so there's never any shifting crosstalk - they're just at fixed locations on screen.
By the way, I want most programs written for FCCF to run on both PAL and NTSC machines without any specific code for each format, perferrably not even a 'if PAL' branch. That's another reason why I prefer 'reset both PPU' over 'clock-gate the missing pixel'.
PAL PPUs would never have any reason to use the "reset both PPUs" thing - they stay permanently synced.
Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

Ben Boldt wrote: Sat Apr 09, 2022 9:41 am You can use presettable counters and set the preset values for a specific count.
That's a good idea. But even that requires 5 74LS161s, still a lot of chip.
74HC4060 is also great, but you need 2 chips (2 reloadable counters or a dual counter and a decoder) to let it count exactly 21 times, then use another bunch of circuits to count the rest of the cycles. Plus, all of these solutions require gating exactly the missing pixel, not any other pixels. Othrewise a visible 'gap' would appear somewhere in the screen.
Andy18650
Posts: 43
Joined: Sat Mar 26, 2022 9:58 pm

Re: FamiCom CrossFire-an NES with two PPUs

Post by Andy18650 »

After going over quite a few ideas, I decided to not use the clock-gating method. I admit that it is a light-handed solution to a light problem, and it isn't unduable. HOWEVER, in my opinion the engineering complexity is just pushing things to the 'unrealistic' side. I did say that the FCCF is 'very much a fantasy console', but I did not mean I don't want to realize it. Indeed you can still do it, but possibly with a PC/XT-sized motherboard instead of a C64 sized one.

The solution chosen is: a circuit to make sure that both PPUs are started synchronized (That require an actively driven RST line controlled by something like a schmitt gate with RC input, or the CPU can just write the RST register during POST); a note in the programmer's reference to never actually turn off rendering usless absolutely necessary (instead just turn off background and move sprites off-screen or just write zeros to the register between the EXT pins); and a way to RST both PPUs at the same time if the programmer thinks they might have drifted away and needs to put them back in a known state (and the blank screen issue should be dealt with manually).

I also want to include that register in PAL machines, although it has been repeatedly said that PAL PPUs will stay synchronized. I think that relying on the PPUs to stay in sync after billions of cycles justbecause they started synchronized and share the same clock is a little bit too 'open loop'. And the idea that if the PPUs has drifted out of sync (because of some random EMI, for example), nothing can be done until a hard reset doesn't sound very robust to me.

Again, I know this is not a good solution, but it works and is far less complex than alternatives. But, I mean, the Famicom/NES itself is not free from problems/inconveniences in the name of engineering simplicity. (The bit 6 in $2000 is essentially a Killer Poke!) The decision is still not final, though. Please leave some comments below.

P.S. should we start naming some terms for the FCCF? For example, call the PPUs 'primary' (the one that does video ouputting) and 'secondary' (the one that feeds the 'primary' PPU data through the EXT pins) instead of 'master' and 'slave' (I don't even know which one is which) seemingly desinated by Ricoh, as those terms are... unpopular these days. And I suggest we call the register between the EXT pins 'palette translation register'. It's not accurate, because what it 'translates' is actually palette index not the palette itself, but it's close enough.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: FamiCom CrossFire-an NES with two PPUs

Post by lidnariq »

Unless you decide to make both video outputs available? Then you could choose between "external cart slot has graphics for foreground layer" and "external cart slot has graphics for background layer"

As roles, I'd probably refer to them as "compositor" and "background"
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: FamiCom CrossFire-an NES with two PPUs

Post by Ben Boldt »

Andy18650 wrote: Sun Apr 10, 2022 11:05 am That's a good idea. But even that requires 5 74LS161s, still a lot of chip.
Right now we do not have a simple discrete solution. There is a CPLD. If you do things 1:1, it will probably take a whole bunch of digital logic chips; yes I completely agree with that. BUT it is basically guaranteed possible.

Fully understanding the requirements (which I do not), there are likely to be a number of clever shortcuts that can be taken. You stated that you wanted to use technology from the 1980s instead of a CPLD, and this is the path. Start with a complicated design that replicates the CPLD's program. Then from there, the path of progression is finding ways to take shortcuts to reduce your chip count. Like I said, there are all sorts of different chips designed to count, and I gave an example of one that can count pretty large numbers. That is the way that it is/was done if you want to stay true to the 1980s.
Andy18650 wrote: Sun Apr 10, 2022 11:05 am 74HC4060 is also great, but you need 2 chips (2 reloadable counters or a dual counter and a decoder) to let it count exactly 21 times, then use another bunch of circuits to count the rest of the cycles.
You see, that is the incorrect approach. You have to start by brainstorming, which requires you to stay open to ideas that aren't immediately a solution yet. You may, for example, use a 74HC4060 + some other counter. For the first 21 counts of that other counter, you loop through the full 4060. Then the rest of the counts are the rest of the counts. You can use some of the lower-order outputs of the 4060 for count 22, 23, 24, etc. There are lots and lots of options to think about, each requiring different amounts of supporting logic. To be good at this sort of thing (if you want to), you have to entertain those ideas instead of right away saying, "that's too hard" or too many chips, etc. Everything you work through, even if it results in more chips, gives you more paths to think about. You will find that combining 2 terrible ideas can sometimes come out ahead. A lot of people like projects to be more deterministic and straightforward to design than that, and for those folks, we have the CPLD.
Andy18650 wrote: Sun Apr 10, 2022 11:05 am Plus, all of these solutions require gating exactly the missing pixel, not any other pixels. Othrewise a visible 'gap' would appear somewhere in the screen.
This seems like a fairly separate feature of the circuit than counting to 700,000. Can you think of any way to combine this, reuse your same counter(s), which are no longer serving a purpose when waiting for the magic pixel?

You might be surprised, but a solution that seems complicated and starts with 20 chips can often get down to 5 or 4 chips if you really obsess over it. How familiar are you with digital logic? Do you know all the weird digital design stuff: D'Morgan's Law, K-maps, excitation tables, etc?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: FamiCom CrossFire-an NES with two PPUs

Post by lidnariq »

Andy18650 wrote: Sun Apr 10, 2022 11:27 am I also want to include that register in PAL machines, although it has been repeatedly said that PAL PPUs will stay synchronized. I think that relying on the PPUs to stay in sync after billions of cycles just because they started synchronized and share the same clock is a little bit too 'open loop'. And the idea that if the PPUs has drifted out of sync (because of some random EMI, for example), nothing can be done until a hard reset doesn't sound very robust to me.
The problem is worse than that: detecting them having drifted out of sync is particularly expensive. You either have to write your code to be extra paranoid and slow, or else you just assume it's working. So when would one use the reset? Either all the time, which is burdensome and will result in the screen flashing a lot, or never.

As far as detecting the missing dot: you don't need to count the number of master clocks in one whole redraw. (In fact, you don't want to. If you wait that long, the entire viewport will shimmer relative to the other PPU.) Instead, detect start of hsync, and see if /RD (or ALE) are asserted at the correct pixel (which one I forget right now but could figure out). If you see /RD, there's a missing dot and you can immediately use a transmission gate to stop letting the clock through. So yes, you do still have to worry about building digital logic that works at 22MHz, but that is doable.
Post Reply