Bus conflict

From NESdev Wiki
Revision as of 15:09, 3 October 2009 by Tepples (talk | contribs) (→‎Emulating bus conflicts: link to the circuit that the mapper assumed)
Jump to navigationJump to search

A bus conflict occurs when two logic devices output different values on the same bus line. When two signals are asserted at the same voltage, the one with less impedance generally wins. In the NES, this generally happens when a program writes to a mapper whose registers overlap ROM but the ROM does not shut off its output, causing a potential conflict on the PRG data bus. Most ASIC based mappers include logic to disable the ROM's output enable during writes, putting the ROM's outputs into a high-impedance state and preventing the bus conflict. But many mappers, especially discrete logic mappers, do not.

Programming around bus conflicts

If you are using a mapper with bus conflicts, make sure that all devices on the bus are asserting the same value by writing to a ROM location that already contains the value that you are writing. For instance, to switch to bank 5 in UNROM or UOROM, write a 5 to a ROM location that already contains a 5.

One common way to do this is to perform an immediate load and then store over the opcode:

@loadInstruction:
  ldy #5
  sty @loadInstruction+1

To switch to a bank based on the value of a variable, put it in an indexed register and then perform an absolute indexed store:

  lda curMapBank
  tax
  sta bankBytes,x
; ...
bankBytes:
  .byt $00, $01, $02, $03, $04, $05, $06, $07

Emulating bus conflicts

Most emulators have assumed that the CPU "wins" all bus conflicts, that is, that the mapper circuitry sees the signals from the CPU more strongly than the signals from the PRG ROM and acts solely on the CPU. Quite a few early programs in iNES format were developed under the impression that the CPU always wins, and do not work correctly when run on an NES Game Pak that has been modified to take rewritable memory. In general, the authors of these programs did not know at the time that bus conflicts existed. These programs can, however, be made to run by adding ROM-disabling circuitry like that of ANROM. The following classes of iNES files will often contain bugs causing bus conflicts:

  • Old homebrew ROMs. Old documents did not mention the possibility of bus conflicts.
  • Mapper hacks. Because the Nintendo MMC1 was poorly understood, and the code to operate an MMC1 is generally larger than that for a discrete logic mapper without bus conflicts, the early English translations of the Famicom game Final Fantasy II changed it from SNROM to a variant of UOROM modified (explicitly) with 8 KiB of battery-backed PRG RAM and (implicitly) with the ANROM logic.
  • Buggy homebrew or hack. Code or tables to avoid bus conflicts may have been written incorrectly, or a JMP instruction may have sent the program counter into nowhere.

Emulators should log a warning whenever a bus conflict occurs. This will help find bugs 1. in the emulator's handling of PRG ROM bank switching and 2. in future homebrew ROMs tested on the emulator.

See also