Konami VRC2 - $6000

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Konami VRC2 - $6000
by on (#85867)
Ran into a problem with VRC2 that wasn't documented in the Wiki or Disch's docs, so I added it to the Wiki. Posting here to explain the change.

So, since VRC4 is basically (VRC2++)++, it seems most emulators probably just use VRC4 on it, and thus the VRC2 games have 8KB of PRG RAM mapped from $6000-7fff. However, VRC2 lacks any PRG RAM, as you can see from this board screenshot:

http://bootgod.dyndns.org:7777/profile.php?id=1568

And yet, VRC2 games seem to expect to be able to write to $6000.d0, and read back the result. If this fails, the games crash before showing any graphics. This is true for at least Contra (J) and Ganbare Goemon 2 (J). I didn't test any others.

I've verified that neither 0x00 nor CPU MDR (open bus) allow the games to work. Here's a disassembly from Contra (J):

Code:
f863  ldy #$03      A:05 X:00 Y:ff S:ff nvdIzC
f865  tya           A:05 X:00 Y:03 S:ff nvdIzC
f866  and #$01      A:03 X:00 Y:03 S:ff nvdIzC
f868  sta $07e9     A:01 X:00 Y:03 S:ff nvdIzC
f86b  sta $6000     A:01 X:00 Y:03 S:ff nvdIzC
f86e  lda $6000     A:01 X:00 Y:03 S:ff nvdIzC  //returns open bus here
f871  and #$01      A:60 X:00 Y:03 S:ff nvdIzC
f873  cmp $07e9     A:00 X:00 Y:03 S:ff nvdIZC
f876  bne $f87d     A:00 X:00 Y:03 S:ff NvdIzc
f87d  jmp $0000     A:00 X:00 Y:03 S:ff NvdIzc
0000  brk #$01      A:00 X:00 Y:03 S:ff NvdIzc
f8e1  rti           A:00 X:00 Y:03 S:fc NvdIzc
...


I have no idea what $6000.d0 is or does: it may be a chip enable, it may just be a one-bit storage latch. Who knows. Anything can be returned in d1-d7, and nothing needs to happen for $6001-7fff for the games to work.

I've added the info to the Wiki here:

http://wiki.nesdev.com/w/index.php/VRC2 ... .246000.29

Feel free to make any changes/corrections.

by on (#85878)
Shouldn't be hard to get someone with a test cartridge to run a simple program to verify this behavior, or have you already?

by on (#85881)
On real hardware, I'd bet that the address for that latch is more then just $6000.

by on (#85883)
Perhaps any write from $6000 to $FFFF gets latched and can be read back in the $6000 to $7FFF range?

by on (#85884)
MottZilla wrote:
Perhaps any write from $6000 to $FFFF gets latched and can be read back in the $6000 to $7FFF range?


I thought that first, but because VRC2 looks at some of the lower bits it could be $6000,$6004, etc or some other combination.

Like you said though it would be easy to determine.

by on (#85886)
It would be great if someone could test it. I don't have any kind of hardware setup for NES stuff.

What I usually do with empirical research is implement the absolute minimum possible to get something working. If we need more than one bit, or to mirror to more than one address, then we will need to verify it on hardware first. Safer in case homebrew tries to use it.

by on (#85889)
Tested on my Contra cart, d0 does get latched when writing 6000-6fff, there is no effect on the 7000-7fff region, even when writing to that region.

The WRAM area returns open bus normally, when d0 is set, everything in the 6xxx region reads open bus OR'd by 1

You need any other tests done, let me know, I still have the majority of carts in the DB here (submitted by me anyways).

by on (#85891)
Does "open bus" mean the high byte of the address, in this case, 0x60 ORed with 1 (0x61)?

by on (#85894)
Yep, that's a better way of putting it.

by on (#85908)
Quote:
You need any other tests done, let me know


Thank you so much! :D
Really nice of you to test, I appreciate that.

I have two last questions on this chip, if you don't mind.

1. you said open bus OR'ed by 1. So if you write $00 to $6000, then read from $6100, it will return $61 instead of $60? In other words, d0 is not the bit to return, but rather the bit to OR against the return. Just want to be certain. Guessing case 0x6000: return MDR | 6000_write_bit;

2. is the power-on value of $6000.d0 zero, one or undefined (random)? Guessing zero.

Quote:
Does "open bus" mean the high byte of the address, in this case, 0x60 ORed with 1 (0x61)?


I'm not a fan of this method, it fails on the SNES in a few games. I know the NES is more limited, but I'm sure there are ways to read from $6000 without the previous cycle being a fetch from the high-byte of the address.

The technical term is the MDR (memory data register), but emulation authors tend to call it open bus. It's always the last value on the data bus, either from a read or a write.

by on (#85920)
1. Yep, that's it exactly, d0 is OR'd against the return.
2. On power on, the latch is not set, so yes $6000.d0 is 0

Zepper: on second look, it is not always the high-byte of the address returned in the $6xxx region.

$6000-61ff returns $60 or $61 (if latch set)
$6200-63ff returns $62 or $63 (^)
...
$6e00-6fff returns $6e or $6f

The $7xxx region is "normal" though and always returns the high-byte of address

by on (#85923)
BootGod wrote:
Zepper: on second look, it is not always the high-byte of the address returned in the $6xxx region.

$6000-61ff returns $60 or $61 (if latch set)
$6200-63ff returns $62 or $63 (^)
...
$6e00-6fff returns $6e or $6f

The $7xxx region is "normal" though and always returns the high-byte of address


That's what I meant, if not clear. :)

by on (#85926)
byuu wrote:
The technical term is the MDR (memory data register), but emulation authors tend to call it open bus. It's always the last value on the data bus, either from a read or a write.


Is the MDR a bus-holder?

by on (#85929)
????

The 65XXX's data latch (DL) and pre-decode register (PD) are "MDR", open-bus values are from persistent voltage due to parasitic capacitance of IC pins. People call it open-bus because that's what it is, a condition where the bus is open (/not driven/disconnected like an open-connection). This may refer to the full bus width or a single bit. If I understand correctly in this thread there is a register which drives a single bit, D0, and the other bits will return open-bus.

read_value = (previous_bus_value & 0xFE) | (6000_reg & 1)

note that 6000_reg doesn't necessarily return what is written to it. Famicom copiers always map RAM to $6000-7FFF, so that is the basis of this protection.


Bus-holders are similar, but are active/have amplificative properties so will persist forever instead of decay like open-bus. In other words open-bus is unintentional, bus-holders are intentional to prevent oscillations/lower power consumption. AFAIK 65XXX do not have bus-holders but unless you wish to emulate the bus' analog properties in a multi-processor system the keeping mechanism is probably irrelevant.

by on (#85930)
What about this cart who apparently has VRC2 and SRAM ?

EDIT : Fixed the url

by on (#85932)
A lot of web sites block inbound links directly to image files to fight bandwidth abuse, but not to an HTML page that describes the image (an "image page"). But for some reason, NesCartDB block inbound links even to image pages.

by on (#85934)
He means this:
http://bootgod.dyndns.org:7777/profile.php?id=3823

by on (#85941)
tepples wrote:
A lot of web sites block inbound links directly to image files to fight bandwidth abuse, but not to an HTML page that describes the image (an "image page"). But for some reason, NesCartDB block inbound links even to image pages.


You can't link to an image.php page? Been a long time since I messed with it, but I thought it was setup to block just direct links to images themselves. I'll look into it when I get a chance.

I would guess that a VRC2 w/ SRAM would just be mapped over it, so it be unused. Honestly I have no idea what the actual point of the reg is anyways, it's not a chip enable, other functions of the chip work just fine regardless of how it is set.

by on (#85943)
Thanks again BootGod, I've updated the Wiki with the new info.

Interesting that there are some VRC2 boards with RAM. Wouldn't be the NES without exceptions to every rule :D

Also noted that Ganbare Goemon needs 5-bit PRG bank registers in order to work.

by on (#85957)
...

by on (#85977)
At a quick glance, GG2 plays with the $6000 register, but it doesn't get caught up in a endless loop or intentionally crash based on result. Does Contra (J) play OK in RockNES with writes to $6000 blocked? I would think not...

by on (#85978)
BootGod wrote:
At a quick glance, GG2 plays with the $6000 register, but it doesn't get caught up in a endless loop or intentionally crash based on result. Does Contra (J) play OK in RockNES with writes to $6000 blocked? I would think not...


Gryzor (J), checksum 0xB27B8CF4, mapper 23.

Right, it doesn't. It gives an error of "unofficial opcode $FF". Mapper 23 is being emulated with 8K of WRAM for all games, working with (apparently) no problems. Sorry for the confusion.