I'm trying to make a ROM that distinguishes the NES from the Famicom and lists which controllers are plugged into the system. I planned to do this using distinct open bus behavior, but the PowerPak and several emulators are disagreeing again.

Open bus occurs when nothing puts a 0 or 1 on a bit of the data bus during a read. Capacitance holds the old voltages in place for the CPU to use as the value. Reading nonexistent memory, for example, usually leaves the instruction's last byte on the bus, which on 6502 is the address's high byte.

But the PowerPak has been known to interfere with open bus before. Pull-up resistors for 3.3 V to 5 V conversion tend to remove old bits from the data bus. Mindscape games would fail to see presses because they expected open bus on unused bits of the controller port.

D0-D4 of both ports drive 0 on a front-loader, but D2 of port 1 on a top-loader is open bus. I wonder whether running the FDS version of The Legend of Zelda on a PowerPak would cause Pols Voice to self-destruct.

I can tell a serial input (like the standard controller, Super NES Mouse, Power Pad, or Arkanoid knob) from a constant input (like the Zapper trigger or the Arkanoid button).

Open bus on a PowerPak is pull-ups to $FF. I should make my program work with $FF. But with a "real" cartridge, however, APU open bus behaves as expected.

The original rectangular NES controller, the Famicom AV dogbone, and the top-loading NES dogbone appear to behave the same.

Per lidnariq's result, the PPU might not really have open bus. This merits further investigation.

There's a bug in my test program that makes the fourth and eighth bytes in "Controller bits" useless. I'll post a revised test program tomorrow.

I'd like to get results from some Famicoms, especially with controllers that plug in to the DA15 port. Later on, as I make the test ROM more detailed, I'd also like to get results from a variety of unlicensed NES controllers. It'd be more convenient for me to assume that return a string of 1's after the report like the official controllers do, a consequence of the 4021's shift input being tied to ground. But I seem to remember reading that some clone controllers have a string of 0's, as if the 4021's shift input were tied to power.

EDIT 45 minutes later with additional observations, performed on a PowerPak:

If you write to pretty much any PPU register and then read from the nominally write-only register PPUADDR ($2006), you get the same byte back. This gives full control of $4016 open bus through a $3F16-$4016 sequence, so long as you're not on a cart with pull-ups. It's true of PPUDATA ($2007) and PPUMASK ($2001). which are writable, as well as like PPUSTATUS ($2002). And FCEUX already emulates this accurately.

Let me repeat that again, because it shocked me so much: You can write a byte to PPUSTATUS and read it back from PPUADDR. Double shock is that FCEUX is accurate in this respect; its PPU calls the storage for this behavior PPUGenLatch.

Let me repeat that again, because it shocked me so much: You can write a byte to PPUSTATUS and read it back from PPUADDR. Double shock is that FCEUX is accurate in this respect; its PPU calls the storage for this behavior PPUGenLatch.

Well then -- this is certainly wrong. It would mean PPUSTATUS is read-write. But I suppose more research is needed before updating the Wiki.

Thank you. The results from lidnariq's cart match my mental model of what's going on, so now I can explain what the bits mean.

"PPU readback" is the result of reading back two bytes from the nametables four ways: through PPUDATA's base address ($2007), through the mirror at $3F07, through the mirror at $3F17, and through $3F07 riding the open bus to $4007. On authentic hardware, all four pairs should be $00 $FF. With pull-ups on all data lines, the last two will be $FF.

"PPU latch" writes $3F to PPUSTATUS ($2002) and then reads one of the PPUADDR ($2006) mirrors. It reads $2006, $3F06, $3F16, $3F16 64 times taking the last, and $3F16 after waiting a frame. All five should be $3F.

"APU open bus" is the result of reading $4006 and $4007. The first two should be $40. The third was supposed to ride the open bus from $3F06 to $4006, but it's useless due to a typo. I apologize for my typos; long-distance coding is a pain. If you still have the source code handy, please open src/openbus.s, scroll near line 108, and change sta open_bus_values+7 to sta open_bus_values+2 and tell me what that says.

"Controller" is four bytes. I read 32 samples from each controller port directly ($4016 or $4017), wait a frame, restrobe, and read 32 more samples riding the open bus ($3F16+$4016 or $3F17+$4017). The first two bytes in a group of four are the minimum values (all reads ANDed); the second two are the maximum values (all reads ORed). The first and third are from $4016; the second and fourth are from riding the open bus. The following can be observed:

Any bit that differs between the first and second probably comes from open bus.

Any bit that differs between the first and third is probably a serial output.

The $2x comes from the $3F that I use as "background" for maximum contrast with $40. PowerPak is full of Ex and Fx because of the pull-ups.

"PPU latch" writes $3F to PPUSTATUS ($2002) and then reads one of the PPUADDR ($2006) mirrors. It reads $2006, $3F06, $3F16, $3F16 64 times taking the last, and $3F16 after waiting a frame. All five should be $3F.

Fascinatingly, after a few resets, the last byte of the five is consistently 1F or 0F (randomly one of the two, more often the former). A power cycle with three seconds off returns it to $3F, a reset after a few seconds returns it to $1F or $0F.

I think remember previous statements that this "latch" is actually the large capacitance of the very long traces from the pins to the various functions inside the PPU: what visual2c02 calls _io_db0 through _io_db7. Certain values ($55, $AA) should be less stable than others ($FF). _io_db0 is adjacent to pclk0 and pclk1, but since those run 180° out of phase, I'm not clear what the net effect would be, if anything.

Quote:

"APU open bus" is the result of reading $4006 and $4007. The first two should be $40. The third was supposed to ride the open bus from $3F06 to $4006, but it's useless due to a typo. I apologize for my typos; long-distance coding is a pain. If you still have the source code handy, please open src/openbus.s, scroll near line 108, and change sta open_bus_values+7 to sta open_bus_values+2 and tell me what that says.

I have some hardware results from almost everything but a PowerPak (On the other hand, I do have Everdrive N8)

Cart was a Konami NES-UNROM equivalent, converted to support 32-pin FLASH EPROMs and extended to support UOROM.A while back I had converted Zap Ruder and LJ65 to run on this same board, and pretty much just copied the code again. It works well enough to be mostly reliable, and doesn't appear to conflict with the tests done here.

From left to right this is [Cart Only - NES-001], [Everdrive N8 - NES-001 - Cart Only], and [Everdrive N8 - HVC-101 - Cart Only]:

P.S.: Forgot to mention that the folder linked has tests using the cart on an NES-001 with just about every controller I could locate.

Notable quirks:

UForce seems to be detected similar to a controllerThe Power Pad seems to be detected similar to the ZapperThe Four Score detects like two controllers when the switch is set to 4 (I recall being able to detect which controllers are connected by reading the signature past the controller data)The Four Score appears to just pass controller data when the switch is set to 2, but not pass the extra data bits for the Zapper (This was fixed in the Satellite)

Who is online

Users browsing this forum: No registered users and 8 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum