Riding the open bus

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Riding the open bus

Post by tepples »

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.

Here's what I expected:

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF 00 FF
Open bus result
     40 40 20 20 20 3F 3F 3F
Controller bits
     40 40 20 20 41 41 21 21
Here's what FCEUX gives me:

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF 3F 3F
Open bus result
     40 40 00 00 00 00 00 3F
Controller bits
     40 40 00 00 41 41 01 01
And Mednafen:

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF 00 FF
Open bus result
     40 40 FF FF FF FF FF FF
Controller bits
     40 40 00 00 41 41 00 01
The PowerPak behaves as if all lines had pull-ups (I'm a big kid now):

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF FF FF
Open bus result
     FF FF FF FF FF FF FF FF
Controller bits
     E0 E0 E0 E0 E1 E0 E1 E1
What do you get on a modded donor board or INL-ROM?


This test ROM has a known defect. An improved test will be posted soon.
Attachments
allpads-r1.zip
(23.65 KiB) Downloaded 1370 times
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Riding the open bus

Post by koitsu »

Results for me two separate NES consoles (I don't have a 72-to-60-pin converter so I can't use my PowerPak w/ my Famicom AV). Providing console S/Ns "just in case":

PowerPak + NES front-loader (S/N N11526282)

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF FF FF
Open bus result
     FF FF FF FF FF FF FF FF
Controller bits
     E0 E0 E0 E0 E1 E0 E1 E1
PowerPak + NES top-loader (S/N NN104472123)

Code: Select all

PPU readback result
     00 FF 00 FF 00 FF FF FF
Open bus result
     FF FF FF FF FF FF FF FF
Controller bits
     E4 E0 E4 E4 E5 E0 E5 E5
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Riding the open bus

Post by tepples »

Does it change if you put a controller in port 2? On my frontloader, if I have two controllers plugged in, I get

Code: Select all

E0 E0 E0 E0 E1 E1 E1 E1  (2 controllers)
E0 E8 E0 E0 E1 E8 E1 E1  (controller and Zapper)
E0 F8 E0 E0 E1 F8 E1 E1  (controller and Zapper, trigger half-held during Reset)
E0 E0 E0 E0 E1 F0 E1 E1  (controller and Arkanoid paddle)
E0 E8 E0 E0 E1 F8 E1 E1  (controller and Arkanoid paddle, button held during Reset)
E0 E0 E0 E0 E1 F8 E1 E1  (controller and Power Pad)
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Riding the open bus

Post by koitsu »

Further testing (same equipment as earlier):

Code: Select all

E0 E0 E0 E0 E0 E0 E0 E0  (Front-loader, no controllers)
E0 E0 E0 E0 E1 E1 E1 E1  (Front-loader, dogbone #1, Famicom AV dogbone #2)
E0 E8 E0 E0 E1 E8 E1 E1  (Front-loader, dogbone #1, Zapper (orange) #2)
E0 E8 E0 E0 E1 F8 E1 E1  (Front-loader, dogbone #1, Zapper (orange) #2, trigger half-held)
E0 E0 E0 E0 E1 E1 E1 E1  (Front-loader, dogbone #1, original NES controller #2)

E4 E0 E4 E4 E4 E0 E4 E4  (Top-loader, no controllers)
E4 E0 E4 E4 E5 E1 E5 E5  (Top-loader, dogbone #1, Famicom AV dogbone #2)
E4 E8 E4 E4 E5 E8 E5 E5  (Top-loader, dogbone #1, Zapper (orange) #2)
E4 E8 E4 E4 E5 F8 E5 E5  (Top-loader, dogbone #1, Zapper (orange) #2, trigger half-held)
E4 E0 E4 E4 E5 E1 E5 E5  (Top-loader, dogbone #1, original NES controller #2)
That covers all the NES controller port peripherals I have.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Riding the open bus

Post by lidnariq »

It was fast to hack that to mapper 218, so I tested. This is using my mapper 218 flashcart (with an 8KiB EEPROM for PRG), nothing else funny in the way.

Nothing plugged in:

Code: Select all

CODE:04
PPU READBACK RESULT
     00 ff 00 ff 00 ff 00 ff
OPEN BUS RESULT
     40 40 ff ff ff ff ff ff
CONTROLLER BITS
     40 40 80 80 40 40 80 80
Only the last line changed as I changed what was plugged in:
Original square US controller in port 1: 40 40 80 80 41 40 81 81
Original square US controller in both ports: 40 40 80 80 41 41 81 81
Original square US controller in port 1 + zapper in port 2: 40 48 80 80 41 48 81 81
vice versa: 48 40 88 88 48 41 88 88


On the off chance that I could have broken anything, here's the diff:
mapper218-patch.zip
(3.27 KiB) Downloaded 1365 times
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Riding the open bus

Post by tepples »

So I've learned a few things:
  • 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.

This will change how I generate the open bus background for my reads.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Riding the open bus

Post by koitsu »

Some further emulator testing as well, just for comparison (maybe we'll learn something). This is just with one controller attached, using allpads-r1.zip.

VirtuaNES 0.97

Code: Select all

code: 04
PPU readback result
     00 FF 00 FF 00 FF 40 40
Open bus result
     40 40 00 00 00 00 00 40
Controller bits
     40 40 40 40 41 41 40 41
Nestopia UE (2014/08/25 build)

Code: Select all

code: 04
PPU readback result
     00 FF 00 FF 00 FF 40 40
Open bus result
     40 40 FF FF FF FF FF 40
Controller bits
     40 40 40 40 41 41 41 41
Nintendulator 0.975

Code: Select all

code: 04
PPU readback result
     00 FF 00 FF 00 FF 00 FF
Open bus result
     40 40 FF FF FF FF FF FF
Controller bits
     40 40 00 00 41 40 01 01
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Riding the open bus

Post by tepples »

I found and fixed the controller test bugs. I also redesigned the open bus test to account for the existence of the PPU data latch. Here's what my PowerPak in a front-loader gives me now:

Code: Select all

PPU readback
     00 FF 00 FF 00 FF FF FF
PPU latch     3F 3F 3F 3F 3F
APU open bus        FF FF FF
And here's what I get for controllers:
E0 E0 E0 E0: Nothing
E0 E0 E1 E1: D0 serial devices
E0 E0 F8 F8: Power Pad NES-028
E8 E8 E8 E8: Zapper
F8 F8 F8 F8: Zapper, trigger half pulled
E0 E0 F0 F0: Arkanoid controller
E8 E8 F8 F8: Arkanoid controller, button held

The D0 serial devices I tried were Nintendo Controller (NES-004), Retrolink Classic Controller Dogbone Edition, Turbo Touch 360, asciiPad (4900) through a pin adapter, and Super NES Mouse (SNS-016) through a pin adapter.
Attachments
allpads-r2a.zip
The third byte of "APU open bus" has been corrected
(24.31 KiB) Downloaded 1325 times
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Riding the open bus

Post by koitsu »

tepples wrote: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.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Riding the open bus

Post by lidnariq »

I thought it was documented that writes to any register in the PPU, including the non-existant one at $2002, can be read from ~any register except $2004 and $2007?
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Riding the open bus

Post by lidnariq »

Anyway, since my results vary slightly from yours:

Code: Select all

PPU READBACK
     00 ff 00 ff 00 ff 00 ff
PPU LATCH     3f 3f 3f 3f 3f
APU OPEN BUS        40 40 ff

CONTROLLER 1     48 28 48 28  (orange zapper)
CONTROLLER 2     40 20 41 21  (square NES controller)
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Riding the open bus

Post by tepples »

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.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Riding the open bus

Post by lidnariq »

tepples wrote:"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.
"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.
Consistently says 3F now.
User avatar
AWal
Posts: 132
Joined: Wed Oct 06, 2004 8:00 am
Location: Northern New York
Contact:

Open Bus Rider: The Adventure

Post by AWal »

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.

MediaFire folder containing all test screenshots. I did my best to make filenames as accurate as possible.

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

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 controller
    The Power Pad seems to be detected similar to the Zapper
    The 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)
User avatar
Dwedit
Posts: 4921
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Riding the open bus

Post by Dwedit »

Better to attach the files here than to use Mediafire....
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Post Reply