Bus conflict: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
m (transwiki for an article on computer busses)
(→‎Emulating bus conflicts: blargg's test result: AND)
Line 22: Line 22:


== Emulating bus conflicts ==
== 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:
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]] or the positive chip enable of the PRG ROM chips used with [[AOROM]].
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.
* Old homebrew ROMs. Old documents did not mention the possibility of bus conflicts.
 
* Mapper hacks. Because the [[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 [[UxROM|UOROM]] modified (explicitly) with [[PRG RAM circuit|8 KiB of battery-backed PRG RAM]] and (implicitly) with the ANROM logic.
* Mapper hacks. Because the [[MMC1|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 [[UxROM|UOROM]] modified (explicitly) with [[PRG RAM circuit|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 <code>JMP</code> instruction may have sent the program counter into nowhere.
* Buggy homebrew or hack. Code or tables to avoid bus conflicts may have been written incorrectly, or a <code>JMP</code> instruction may have sent the program counter into nowhere.


It has been determined through [http://forums.nesdev.org/viewtopic.php?p=109708#p109708 testing] that both the CPU and the mask ROMs used in the NES era drive a 0 more strongly than a 1.
This implies that an emulator should use the bitwise AND of the value from the CPU and the value from the ROM.
However, programmers must not rely on this undefined behavior.
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.
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 ==
== See also ==
*[[:Category:Mappers with bus conflicts|Mappers with bus conflicts]]
*[[:Category:Mappers with bus conflicts|Mappers with bus conflicts]]

Revision as of 21:36, 18 March 2013

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 or the positive chip enable of the PRG ROM chips used with AOROM. 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 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.

It has been determined through testing that both the CPU and the mask ROMs used in the NES era drive a 0 more strongly than a 1. This implies that an emulator should use the bitwise AND of the value from the CPU and the value from the ROM. However, programmers must not rely on this undefined behavior. 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