https://www.nesdev.org/w/api.php?action=feedcontributions&user=Fiskbit&feedformat=atomNESdev Wiki - User contributions [en]2024-03-29T02:28:18ZUser contributionsMediaWiki 1.39.0https://www.nesdev.org/w/index.php?title=FamicomBox&diff=21722FamicomBox2024-03-27T21:52:32Z<p>Fiskbit: /* Hardware configurations */ Adds the newly-discovered SSS-CPU-02 main board revision (using E/E-0 CPU/PPU). Differences compared to 04 are not yet known.</p>
<hr />
<div>The Nintendo [[FamicomBox]] (SSS-CDS), also released as the Sharp '''FamicomStation''' (AN-560), is a commercial Famicom console with 16 cartridge slots, intended for use in hotels. One internal slot runs the menu software, while the 15 other slots are externally-visible and can be selected by the user through software. These slots take NES-form-factor 72-pin cartridges, but with a modified EXP pinout to support the system's unique 3198 lockout chip. In addition to free-play, play time can be purchased with coins, unlocked with a key, or tracked via a pay-to-play CATV interface.<br />
<br />
The FamicomBox hardware differs significantly from standard consoles. It adds 14 KiB of extra CPU RAM and various hardware registers controlling features such as a reset-based exception system. However, it also has significant limitations that impact its compatibility with the NES library, such as restricting cartridges to just the upper half of the address space, not connecting some of the cartridge pins, and allowing inactive cartridges to interfere with the active one.<br />
<br />
The menu software will refuse to run any game that neither matches a checksum in the menu's game database nor has a valid-enough [[Nintendo header]].<br />
<br />
{{mbox<br />
| type = warning<br />
| text = '''The FamicomBox power supply frequently fails with high-voltage output, which can cause significant system-wide damage. It is strongly recommended that original power supplies be replaced with modern ones that support 100-240V input.'''<br />
}}<br />
<br />
{{mbox<br />
| type = warning<br />
| text = '''Because of the FamicomBox's different EXP pinout, inserting standard NES cartridges or Famicom adapters that use EXP pins into an unmodified FamicomBox may cause damage to the cartridge or console by shorting to 5V or ground.'''<br />
}}<br />
<br />
==Physical description==<br />
The front of the FamicomBox has 3 columns of 5 cartridge slots each, with end labels visible through plastic windows. These are indexed 1-15 top to bottom, left to right. Each slot has an LED to the left. In the bottom center from left to right are a TV/GAME LED (illuminated in game mode), TV/GAME button, reset button, and keyswitch that can be rotated between 6 positions. Three controllers attach through the lower left.<br />
<br />
The front panel is closed via a tubular lock on each of the top left and top right. With the panel open, the 15 cartridge slots can be accessed. On the lower left is a board with 3 joypad ports, the third one used for the Zapper. This board also has a service button for adding credits.<br />
<br />
An optional coin box attaches to the right side of the console. It has a 100 yen coin slot, a coin drawer secured by a tubular lock, and an LED that indicates play time and flashes when play time is low.<br />
<br />
The left side of the console has a holder for the controllers and Zapper.<br />
<br />
The back of the console features various ports. On the left are input and output coaxial RF ports, a switch for channel 1 or 2, and composite AV ports for video and audio. Under these is a panel covering a 50-pin expansion edge connector. To the right are a DB-15 Famicom expansion port, DB-25 expansion port, and 8-pin CATV connector. The CATV connector is used for remote billing. To the right of these are a 5V DC center-negative power input and 10 DIP switches. Further right is a power supply that plugs into the wall, outputs 5V DC center negative via an external cable, has 2 AC output plugs for other devices, and a fuse.<br />
<br />
==CPU address space==<br />
* $0000-1FFF: 8 KiB RAM<br />
* $2000-3FFF: PPU registers<br />
* $4000-401F: APU registers<br />
* $4020-4FFF: Unused<br />
* $5000-5FFF: FamicomBox registers<br />
* $6000-7FFF: 8 KiB RAM<br />
* $8000-FFFF: Cartridge space<br />
<br />
The FamicomBox's CPU address space differs from that of the [[CPU_memory_map|standard console]], adding RAM and registers and reducing space for cartridge mapping. Unlike normal systems, the FamicomBox cuts cartridges off from the CPU data lines when the CPU is accessing under $8000, preventing cartridges from mapping in the unused region.<br />
<br />
==Clock rates==<br />
The FamicomBox uses a 21.47727 MHz system clock. All other clocks are derived from this one. These are as follows:<br />
<br />
* 3.579545 MHz: This divides the system clock by 3*2 and is referred to here as 3.58 MHz. It is used by the 3198 CIC and 3199 coin timer.<br />
* 873.9123 Hz: This divides the system clock by 3*(2^13) and is referred to here as 874 Hz. It is used to generate the near-end flash beep sound.<br />
* 6.827440 Hz: This divides the system clock by 3*(2^20) and is referred to here as 6.83 Hz. It is used by the 6.83 Hz period exception and the 8-bit timer.<br />
* 3.413720 Hz: This divides the system clock by 3*(2^21) and is referred to here as 3.41 Hz. It is used for the slot LED flash rate.<br />
* 0.8534300 Hz: This divides the system clock by 3*(2^23) and is referred to here as 0.85 Hz. It is used by the watchdog counter.<br />
<br />
==Features==<br />
===Slot selection===<br />
The FamicomBox has 16 cartridge slots, separated into 4 "columns" containing slots 0, 1-5, 6-10, and 11-15. The slot and column are selected via [[#Slot_select_($5004W)|$5004W]]. This selection controls multiplexing of various cartridge signals. Slot multiplexing is done on /ROMSEL to only enable the target slot's PRG-ROM, on PPU A13 so only the target slot sees that a PPU access is in the $0000-1FFF range, and on CIRAM A10 to allow the target slot to control nametable mirroring. Column multiplexing is present to combat fanout, ensuring signals are sufficiently strong, and is applied to the CPU and PPU data lines.<br />
<br />
Despite this multiplexing, inactive slots in the system are still connected enough that they may respond to accesses, potentially interfering with the active slot. This multiplexing, however, was sufficient for the FamicomBox's limited selection of games.<br />
<br />
====Cartridge compatibility====<br />
See: [[#Cartridge_connector|Cartridge connector pinout]]<br />
<br />
Cartridges are selected by multiplexing certain pins by slot, but some are by column, most aren't muxed at all, and some signals aren't even present on the slots. This leads to significant compatibility limitations. The following signals encounter problems:<br />
* '''/IRQ''': Most mappers that use /IRQ drive the pin at all times (despite it being intended to be open collector/drain), which interferes with IRQs from any other slot.<br />
* '''M2''': Unlike /ROMSEL, M2 is not muxed. Cartridges that map under $8000 determine the value of CPU A15 using /ROMSEL and M2. Because /ROMSEL is held high for inactive slots, these cartridges will see any CPU access to $8000-FFFF as an access to $0000-7FFF, which may cause unintended mapper register or PRG-RAM accesses. For reads, this can cause bus conflicts with other slots. The CPU data lines are muxed by column, so conflicts will occur within a single column. On the active column, any such cartridges can cause bus conflicts with the active slot, corrupting the value seen by the CPU. These unintended accesses will also occur when explicitly accessing addresses under $8000, but because columns are isolated from the CPU data lines during such accesses, the cartridges cannot see nor influence the value on the CPU side.<br />
* '''CPU D7..0''': The CPU data lines are only passed through when /ROMSEL is asserted, so cartridges cannot map nor snoop below $8000. Games that use PRG-RAM at $6000-7FFF will still work because the console provides RAM there, but it isn't battery-backed and any stateful RAM on the cartridge will be corrupted by writes (see M2 above). When disabled, it is suspected the SN74ALS245's that isolate the columns maintain the current line levels, effectively creating an open bus that does not decay.<br />
* '''PPU D7..0''': The PPU data lines are only passed through when PPU /A13 is asserted, so cartridges cannot map nor snoop $2000 or above. This prevents cartridge nametable RAM or ROM. When disabled, it is suspected the SN74ALS245's that isolate the columns maintain the current line levels, effectively creating an open bus that does not decay.<br />
* '''CIRAM /CE''': PPU /A13 is directly connected by the console to CIRAM /CE, so cartridges cannot disable this RAM for accesses at $2000 or above nor map CIRAM under $2000. This prevents cartridge nametable RAM or ROM and use of CIRAM as pattern table RAM.<br />
* '''PPU A12''': Some cartridges place a capacitor on PPU A12, which can slow transitions enough to interfere with the active slot.<br />
* '''PPU /A13''': This pin is not connected on the FamicomBox. While it's normally only used for controlling CIRAM /CE, both MMC5 and Sunsoft 4 mappers take PPU /A13 as an input instead of PPU A13.<br />
* '''PPU /RD''' and '''PPU /WR''': All cartridges see that a PPU read or write is occurring, but for non-selected slots, PPU A13 multiplexing makes the address appear as though it is a nametable address, which is usually ignored. However, cartridges with nametable RAM or ROM may respond to reads and can cause bus conflicts in the same column, and cartridges with nametable RAM may be written by writes.<br />
* '''EXP4''': This is used for CPU A15, which could cause issues for cartridges configured for an NES-001 expansion device.<br />
* '''EXP0..3''', '''EXP5..9''': These are tied to ground or +5V and can cause physical damage. Examples of susceptible cartridges include those with an opamp on EXP6 or which connect EXP0 to ground (to match the Famicom ground pin at this relative location).<br />
<br />
===Reset===<br />
When the FamicomBox is reset, the CPU and PPU are both reset and the $5002W, $5004W, and $5005W registers are cleared. The system can be reset in a number of ways. While it does have a reset button, this button does not directly control reset, but instead uses the [[#Exceptions|exception system]]. Reset occurs under any of the following conditions:<br />
* The active slot provided incorrect CIC data, causing the host 3198 CIC to do a single reset pulse.<br />
* An [[#Exceptions|exception]] occurred, resetting the host 3198 CIC for 1.76 ms. While in reset, the CIC's outputs are pulled down, activating its host /reset output.<br />
* The console is in [[#TV_and_Game_modes|TV Mode]]. The console can be switched back to Game Mode, releasing it from reset, by pressing the TV/GAME button. TV Mode is activated in the following ways:<br />
** The TV/GAME button is pressed while in Game Mode.<br />
** CATV Billing Clear is asserted.<br />
<br />
===TV and Game modes===<br />
The FamicomBox offers TV and Game modes. In Game Mode, the FamicomBox operates as normal, generating video and audio that it outputs through its RF modulator. In TV Mode, the FamicomBox is held in reset and its RF modulator passes its coaxial input through to its coaxial output. The FamicomBox powers up into Game Mode. It is switched from Game Mode to TV Mode by pressing the TV/GAME button or asserting CATV Billing Clear. It is returned to Game Mode by pressing the TV/GAME button. When entering TV Mode, the TV Mode latch on [[#Miscellaneous_input_($5007R)|$5007R]] D0 is set, allowing menu software after returning to Game Mode to detect that the reset was caused by TV Mode.<br />
<br />
According to the manual's schematic, the FamicomBox was intended to allow the menu software to disable the TV/GAME button via $5005W /D4 (1 = disable) and enter TV mode via $5005W D5, but this functionality is not present on any known revision of the SSS-CPU board.<br />
<br />
===Exceptions===<br />
See: [[#Exception_enable_($5000W)|Exception enable ($5000W)]], [[#Exception_flags_($5000R)|Exception flags ($5000R)]]<br />
<br />
The FamicomBox features 8 kinds of exceptions. When the console transitions from having 0 to 1 active exceptions (enabled exceptions with conditions met), the console is reset by holding the 3198 CIC in reset for 1.76 ms and the [[#Exception_flags_($5000R)|$5000R]] register becomes held in the latched state, latching the current active exception state if it was unlatched. This exception behavior then cannot happen again until the number of active exceptions becomes 0 (all active exceptions become inactive either by being disabled or having their conditions no longer met). When all exceptions are inactive, reading [[#Exception_flags_($5000R)|$5000R]] unlatches it, but still provides the latched value on that read.<br />
<br />
The exceptions are as follows:<br />
* '''6.83 Hz period expiration''': This ensures the internal slot is running FamicomBox-aware software. The condition is true while the 6.83 Hz clock is low. Unlike the other exceptions that can be toggled, this one is enabled at power-on and will repeatedly reset the system unless disabled.<br />
* '''8-bit timer expiration''': This is used to run a game in attract mode for a limited amount of time. The condition is true while the upper 4 bits of the [[#8-bit_timer_($5003W)|$5003W]] timer are 0. This timer is clocked by the inverse of the 6.83 Hz clock.<br />
* '''Joypad button press''': This exception is used to detect button presses for exiting attract mode. The condition is true while joypads 1 and 2 are enabled ([[#Miscellaneous_output_($5005W)|$5005W]] D6), joypad 1 or 2's D0 is asserted, and that joypad hasn't been read 8 or more times since the last strobe. This can be true even if a joypad is not currently being read because it is still outputting on D0. Note that the read count applies to the joypad port, not the register, so swapping joypads ([[#Miscellaneous_output_($5005W)|$5005W]] D7) will also swap the read counts.<br />
* '''Keyswitch rotation''': This exception is used to detect when the keyswitch is rotated to a new position. The condition is true for 13.4 ms after moving from an invalid angle to a valid position (that is, when the state transitions from all bits 0 to any bits being 1). This can also be checked through [[#Miscellaneous_input_($5007R)|$5007R]] /D1.<br />
* '''Credit transition''': This exception triggers when transitioning either way between having and not having credit. This is controlled by the 3199 coin timer and is a pulse.<br />
* '''Reset button press''': This is true while the reset button on the front panel is pressed. When disabled, the reset button has no effect.<br />
* '''Joypad watchdog''': This exception recovers if the software has locked up. It is implemented using a 4-bit up counter clocked at 0.85 Hz that is cleared on read of either joypad. The condition is true while the counter is 15. Unlike other exceptions, this one cannot be disabled.<br />
* '''CATV device disconnection''': This exception triggers if the CATV connection is lost. The condition is true while the CATV Operation On latch (CATV pin 1) is high or open, indicating a CATV device is not connected.<br />
<br />
===Zapper detection===<br />
Joypad port 3 is intended for use with the Zapper. The ground pin of this port can be disconnected from ground via [[#Miscellaneous_output_($5005W)|$5005W]] D2, disabling the device. When this is done, the ground line is weakly pulled low through a 100k ohm resistor. The value on the ground line can be read via [[#Miscellaneous_input_($5007R)|$5007R]] D2. If the Zapper is not connected, this will read as 0 because of that pulldown. However, the Zapper has a pullup effect on ground of about 10k ohm, stronger than the pulldown, which will cause the line to read as 1 slightly more than one frame after disconnecting ground. Therefore, if one disconnects ground and waits at least 2 frames, the presence of the Zapper can be detected using the ground line value.<br />
<br />
===40% brightness===<br />
The RF modulator can be configured to reduce the screen's brightness. This is enabled via [[#Miscellaneous_output_($5005W)|$5005W]] D3 or by the 3199 coin timer during near-end flash. While the effect is called 40%, it has been measured as reducing brightness to about 45% overall. If voltages are taken relative to sync tip rather than blanking, then resulting brightness can be calculated with the function <code>dim(bright) = 8.3906 * bright**(0.62567)</code>, with colorburst H being about 53% brightness, color $00 about 48%, color $10 about 46%, and color $20 about 45%. This effect should be multiplicative with the about-75% brightness resulting from using all 3 of the PPU's color emphasis bits.<br />
<br />
===Coin timer and near-end flash===<br />
When using coins for payment, the 3199 coin timer tracks the remaining time, signals that time is low, and sends an exception pulse when transitioning between having and not having time. The timer is a Sharp SM59x 4-bit CPU like the CIC, but its ROM has not been fully dumped and its behavior is not fully understood.<br />
<br />
When time is running low, the 3199 coin timer outputs a near-end flash (/NEF) signal. This alternates between active and inactive until either time runs out or more coins are added. When active, this triggers 3 different low-time alerts:<br />
* The coin box LED is disabled.<br />
* If DIP switch 9 is off, an 874 Hz beep sound is mixed into the console's audio output.<br />
* If it's not already enabled via [[#Miscellaneous_output_($5005W)|$5005W]] D3, the screen brightness is reduced using the RF modulator's [[#40%_brightness|40% brightness]] feature.<br />
<br />
The rate at which near-end flash alternates is believed to be controlled by the coin timer's NMI/2 input. ''240p Test Suite'' has been observed slowing the rate at which it alternates, but the cause of this is not yet known.<br />
<br />
===CATV interface===<br />
See: [[#CATV_interface_terminal_(RP-3)|CATV interface terminal (RP-3)]]<br />
<br />
The CATV interface provides a pay-to-play billing mechanism, tracking playtime via an external computer system for later payment. Signals on the CATV pins are active low. The FamicomBox detects a CATV connection via the Operation On latch on CATV pin 1, which is tied to the ground input on pin 4. An exception can be generated when this line is no longer driven low, indicating a loss of connection. This state can also be read by the menu software via [[#Miscellaneous_input_($5007R)|$5007R]] D4.<br />
<br />
The FamicomBox contains a relay that tracks whether the user has provided billing authorization. This relay controls CATV pin 3, and its state can be read by the menu software via [[#Miscellaneous_input_($5007R)|$5007R]] /D5. Menu software is able to set the relay to the authorized state by setting [[#Miscellaneous_output_($5005W)|$5005W]] D0 to 1 for at least 75 ms (5 frames). This bit should then be cleared. If the user attempts to start a game and billing is not yet authorized, the menu software should display a screen requesting authorization and then set the relay if authorized by the user. Even if billing is authorized, it is expected that the menu software not allow games to be played while the Operation On latch is inactive, and should instead enter attract mode.<br />
<br />
The relay is reset back to the not-authorized state when a Billing Clear pulse is received via CATV pin 6. This pulse should last for 75 ms. This pulse (of any duration) also places the system into TV Mode. It is expected to be sent when the Operation On latch becomes active, but may also be sent anytime, even while the Operation On latch is inactive.<br />
<br />
When billing is authorized and the Operation On latch is active, the menu software should allow games to be played. While a game is running, the menu software should indicate so via the Game Active signal on [[#Payment_($5001W)|$5001W]] D6, which is sent over CATV pin 7. When exiting the game, Game Active should be cleared. The external system can track the amount of playtime for billing using this Game Active signal.<br />
<br />
The CATV interface also contains an Energized signal on CATV pin 8 indicating the FamicomBox is functional, controlled via [[#Payment_($5001W)|$5001W]] D7. The menu software only sets this if it successfully [[#Zapper_detection|detects the presence of the Zapper]] on joypad port 3. This signal can be used by the external system to detect that the FamicomBox is either not running or its Zapper has been vandalized.<br />
<br />
==Registers==<br />
===Joypad out ($4016W)===<br />
This is wired the same as in an AV Famicom, but OUT0 is not connected to joypad port 3.<br />
<br />
===Joypad 1 in ($4016R)===<br />
Mask: $FFFF<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
|||| |||+- Joypad port 1 D0<br />
|||| ||+-- 15P expand pin 13<br />
|||| |+--- Expansion connector (P4) pin 44<br />
|||| +---- Joypad port 1 D3<br />
|||+------ Joypad port 1 D4<br />
||+------- Expansion connector (P4) pin 19<br />
|+-------- Expansion connector (P4) pin 45<br />
+--------- Expansion connector (P4) pin 20<br />
<br />
Note: All bits are active low.<br />
Note: Any bit not driven by an input device is pulled high (reads as 0).<br />
<br />
Because all joypad read bits are driven, games such as ''Paperboy'' that depend on open bus will not work.<br />
<br />
===Joypad 2 in ($4017R)===<br />
Mask: $FFFF<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
|||| |||+- Joypad port 2 D0, and 15P expand pin 8<br />
|||| ||+-- 15P expand pin 7<br />
|||| |+--- 15P expand pin 6<br />
|||| +---- Joypad port 2 D3, joypad port 3 D3, and 15P expand pin 5<br />
|||+------ Joypad port 2 D4, joypad port 3 D4, and 15P expand pin 4<br />
||+------- Expansion connector (P4) pin 17<br />
|+-------- Expansion connector (P4) pin 43<br />
+--------- Expansion connector (P4) pin 18<br />
<br />
Note: All bits are active low.<br />
Note: Any bit not driven by an input device is pulled high (reads as 0).<br />
<br />
D3 and D4 on joypad ports 2 and 3 can be disabled using DIP switch 10.<br />
<br />
===Exception enable ($5000W)===<br />
Mask: $F007<br />
Power-on value: $00<br />
<br />
7 bit 0<br />
---- ----<br />
V.RC KJTP<br />
| || ||||<br />
| || |||+- 6.83 Hz period expiration (0 = enable)<br />
| || ||+-- 8-bit timer expiration (1 = enable)<br />
| || |+--- Joypad button press (1 = enable)<br />
| || +---- Keyswitch rotation (1 = enable)<br />
| |+------ Credit transition (1 = enable)<br />
| +------- Reset button press (1 = enable)<br />
+--------- CATV device disconnect (1 = enable)<br />
<br />
Note that the watchdog exception cannot be disabled.<br />
<br />
See [[#Exceptions|Exceptions]] for details.<br />
<br />
===Exception flags ($5000R)===<br />
Mask: $F007<br />
Power-on state: either unlatched, or latched and probably $FF<br />
<br />
7 bit 0<br />
---- ----<br />
VWRC KJTP<br />
|||| ||||<br />
|||| |||+- 6.83 Hz period expired<br />
|||| ||+-- 8-bit timer expired<br />
|||| |+--- Joypad button pressed<br />
|||| +---- Keyswitch rotated<br />
|||+------ Credit transitioned<br />
||+------- Reset button pressed<br />
|+-------- Joypad watchdog triggered<br />
+--------- CATV device disconnected<br />
<br />
Note: All bits are active low.<br />
<br />
See [[#Exceptions|Exceptions]] for details.<br />
<br />
===Payment ($5001W)===<br />
Mask: $F007<br />
Power-on value: $00<br />
<br />
7 bit 0<br />
---- ----<br />
EACC CCCC<br />
|||| ||||<br />
|||| |||+- Coin timer (3199) R0.0 (TS0)<br />
|||| ||+-- Coin timer (3199) R0.1 (TS1)<br />
|||| |+--- Coin timer (3199) R0.2 (TS2)<br />
|||| +---- Coin timer (3199) R0.3 (CC0)<br />
|||+------ Coin timer (3199) R1.3 (CC1)<br />
||+------- Coin timer (3199) R2.1 (CH)<br />
|+-------- CATV Game Active (1 = active). Inverse of CATV pin 7.<br />
+--------- CATV Energized (1 = energized). Inverse of CATV pin 8.<br />
<br />
* TS2-0 appear to be related to time per coin. These are set by the menu software to %001 for the 10 minute DIP switch 2 setting and %010 for the 15 minute setting. See [[#3199A_coin_timer|3199A coin timer pinout]] for more details on these and other coin timer pins.<br />
* CH is hypothesized as telling the coin timer to run the timer.<br />
* CATV Energized is set by menu software only if the Zapper is detected via $5007R /D2. See [[#Zapper_detection|Zapper detection]] and [[#CATV_interface|CATV interface]] for details.<br />
<br />
===LED and Memory protect ($5002W)===<br />
Mask: $F007<br />
Reset value: $00<br />
<br />
7 bit 0<br />
---- ----<br />
FMMM LLLL<br />
|||| ||||<br />
|||| ++++- LED select (0 = none)<br />
|+++------ $0000-1FFF memory protect:<br />
| 0 = $0000-1FFF read-only<br />
| 1 = $0800-1FFF read-only<br />
| 2 = $1000-1FFF read-only<br />
| 3 = $1800-1FFF read-only<br />
| 4-7 = all writable<br />
+--------- Flash LED at 3.41 Hz (1 = enable)<br />
<br />
This register controls the 15 LEDs adjacent to the 15 game cartridge slots. Only one can be lit at a time.<br />
<br />
===DIP switches ($5002R) ===<br />
Mask: $F007<br />
<br />
7 bit 0<br />
---- ----<br />
8765 4321<br />
|||| ||||<br />
++++-++++- Switches 8-1 (left = 0, right = 1)<br />
<br />
Behavior is software-defined. See [[#DIP_switch_settings|DIP switch settings]] for details.<br />
<br />
===8-bit timer ($5003W)===<br />
Mask: $F007<br />
Power-on value: Probably $FF<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
++++-++++- Timer value<br />
<br />
This is a down counter that decrements using the inverse of the 6.83 Hz clock. The 8-bit timer exception is triggered when the timer's upper 4 bits are 0. Because of this, the value written should be 15 more than desired. The timer should be set before enabling the exception.<br />
<br />
===Keyswitch ($5003R)===<br />
Mask: $F007<br />
<br />
7 bit 0<br />
---- ----<br />
NAKK KKKK<br />
|||| ||||<br />
||++-++++- Keyswitch position<br />
|+-------- Coin timer (3199) ACT<br />
+--------- Coin timer (3199) NE<br />
<br />
* The keyswitch has 6 positions, each corresponding to one bit in this register. A bit returns 1 if the keyswitch is in that position. All bits are 0 while the keyswitch is rotated between positions. The behavior triggered by each position is software-defined.<br />
* NE is not used by contemporary menu software.<br />
<br />
===Slot select ($5004W)===<br />
Mask: $F007<br />
Reset value: $00<br />
<br />
7 bit 0<br />
---- ----<br />
.RCC SSSS<br />
||| ||||<br />
||| ++++- Slot select<br />
|++------ Column select:<br />
| 0: Slot 0<br />
| 1: Slots 1-5<br />
| 2: Slots 6-10<br />
| 3: Slots 11-15<br />
+-------- Unmap $5000-5FFF registers (1 = unmap)<br />
<br />
* The slot select and column select control multiplexing of certain cartridge connector pins. See [[#Slot_selection|Slot selection]] and [[#Cartridge_connector|Cartridge connector]] for details.<br />
* The unmap feature disables all of the register enables, but does not disable the /$5000-5FFF signal on expansion connector (P4) pin 40. Note that once unmapped, registers stay unmapped until reset.<br />
<br />
===25P expand input ($5004R)===<br />
Mask: $F007<br />
Power-on value: Unknown<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
|||| |||+- DB-25 pin 2<br />
|||| ||+-- DB-25 pin 15<br />
|||| |+--- DB-25 pin 3<br />
|||| +---- DB-25 pin 16<br />
|||+------ DB-25 pin 4<br />
||+------- DB-25 pin 17<br />
|+-------- DB-25 pin 5<br />
+--------- DB-25 pin 18<br />
<br />
Note: All bits inverted<br />
<br />
===Miscellaneous output ($5005W)===<br />
Mask: $F007<br />
Reset value: $00<br />
<br />
7 bit 0<br />
---- ----<br />
SJO. DZCB<br />
||| ||||<br />
||| |||+- Set billing relay to authorized (1 = set)<br />
||| ||+-- Coin timer reset (1 = reset)<br />
||| |+--- Enable joypad port 3 (1 = enable)<br />
||| +---- Enable "40%" screen brightness (0 = enable)<br />
||+------- $5007R /D7 and expansion connector (P4) pin 23<br />
|+-------- Disable joypads 1 and 2 (1 = disable)<br />
+--------- Swap joypads 1 and 2 (1 = swap)<br />
<br />
* The billing relay controls the output of the Billing Authorized latch on CATV connector pin 3. This should be set for at least 75 ms to reliably set the relay. Billing can only be authorized by software and can only be revoked by the Billing Clear input on CATV connector pin 6. See [[#CATV_interface|CATV interface]] for details.<br />
* The coin timer will be held in reset as long as coin timer reset is 1.<br />
* The joypad port 3 enable controls the port's ground line. When disabled, the Zapper will not function and can be detected. See [[#Zapper_detection|Zapper detection]] for details.<br />
* 40% brightness reduces the screen brightness. See [[#40%_brightness|40% brightness]] for details.<br />
* When joypads 1 and 2 are disabled, the joypads can no longer receive joypad /OE or send D0. They still receive OUT0.<br />
* Swapping joypads 1 and 2 swaps joypad /OE and D0 between joypads. It is used by the menu software to allow the controller that selected the game to be joypad 1.<br />
<br />
===Expansion input ($5005R)===<br />
Mask: $F007<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
++++-++++- Open bus<br />
<br />
The enable for this register is outputted over expansion connector (P4) pin 28. A response can be sent over the CPU data lines on the same connector.<br />
<br />
===25P expand output ($5006W)===<br />
Mask: $F007<br />
Power-on value: Probably $FF<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
|||| |||+- 25P expand pin 6<br />
|||| ||+-- 25P expand pin 15<br />
|||| |+--- 25P expand pin 7<br />
|||| +---- 25P expand pin 16<br />
|||+------ 25P expand pin 8<br />
||+------- 25P expand pin 17<br />
|+-------- 25P expand pin 9<br />
+--------- 25P expand pin 18<br />
<br />
===Expansion input ($5006R)===<br />
Mask: $F007<br />
<br />
7 bit 0<br />
---- ----<br />
DDDD DDDD<br />
|||| ||||<br />
++++-++++- Open bus<br />
<br />
The enable for this register is outputted over expansion connector (P4) pin 27. A response can be sent over the CPU data lines on the same connector.<br />
<br />
===Expansion output ($5007W)===<br />
Mask: $F007<br />
<br />
Unimplemented<br />
<br />
The enable for this register is outputted over expansion connector (P4) pin 2. The data is sent over the CPU data lines on the same connector.<br />
<br />
===Miscellaneous input ($5007R)===<br />
Mask: $F007<br />
<br />
7 bit 0<br />
---- ----<br />
IEBC EZKT<br />
|||| ||||<br />
|||| |||+- TV mode latch (0 = game, 1 = TV). Cleared on read.<br />
|||| ||+-- Keyswitch rotated (0 = true)<br />
|||| |+--- Joypad port 3 ground value (1 = device present)<br />
|||| +---- Inverse of expansion connector (P4) pin 21<br />
|||+------ CATV device connected (1 = connected). Inverse of CATV pin 1, Operation On latch.<br />
||+------- Billing relay state (0 = authorized)<br />
|+-------- Inverse of expansion connector (P4) pin 22<br />
+--------- $5005W /D5<br />
<br />
* The TV mode latch is set when entering TV mode and can be used by the software to detect that a reset was caused by TV mode. See [[#TV_and_Game_modes|TV and Game modes]] for details.<br />
* Keyswitch rotated will show as 0 for 13.4 ms after the keyswitch enters a position (keyswitch position transitioned from all bits 0 to any bits being 1). This is the same state used as the condition for the keyswitch rotation exception, just inverted.<br />
* When joypad port 3 ground is disabled, this bit can be used to detect a device. See [[#Zapper_detection|Zapper detection]] for details.<br />
<br />
==DIP switch settings==<br />
Switches are 0 to the left and 1 to the right.<br />
<br />
===Software settings===<br />
* 1: Operation mode (0 = game, 1 = self check)<br />
* 2: Play time per coin (0 = 10 minutes, 1 = 15 minutes)<br />
* 3: Unused<br />
* 4: FamicomBox title screen attract time (0 = 6 seconds, 1 = 11 seconds)<br />
* 5: Game demo time<br />
* 6: Game demo time<br />
* 7: Billing mode<br />
* 8: Billing mode<br />
<br />
{| class="tabular"<br />
! SW6|| SW5 || Game demo time || Timer value<br />
|-<br />
| 0 || 0 || 10 seconds || $54<br />
|-<br />
| 0 || 1 || 15 seconds || $77<br />
|-<br />
| 1 || 0 || 20 seconds || $9A<br />
|-<br />
| 1 || 1 || 5 seconds || $31<br />
|}<br />
<br />
{| class="tabular"<br />
! SW8|| SW7 || Billing mode<br />
|-<br />
| 0 || 0 || Key<br />
|-<br />
| 0 || 1 || CATV<br />
|-<br />
| 1 || 0 || Coin<br />
|-<br />
| 1 || 1 || Free play<br />
|}<br />
===Hardware settings===<br />
* 9: Disable near-end flash beeping (1 = disable). (P6 pin 1)<br />
* 10: Disable joypad 2 D3 and D4 on joypad ports 2 and 3 (1 = disable). This disables the Zapper input. This does not affect the 15P expand inputs. (P6 pin 36)<br />
<br />
==Pinouts (external)==<br />
===Cartridge connector===<br />
FamicomBox | Cart | FamicomBox<br />
-----------<br />
+5V -- |36 72| -- GND<br />
CIC toMB <- |35 71| <- '''CIC CLK (3.58 MHz)'''<br />
CIC toPak -> |34 70| <- CIC +RST<br />
PPU D3 <> |33 '''C''' '''C''' 69| <> PPU D4<br />
PPU D2 <> |32 '''C''' '''C''' 68| <> PPU D5<br />
PPU D1 <> |31 '''C''' '''C''' 67| <> PPU D6<br />
PPU D0 <> |30 '''C''' '''C''' 66| <> PPU D7<br />
PPU A0 -> |29 '''S''' 65| <- PPU A13<br />
PPU A1 -> |28 64| <- PPU A12<br />
PPU A2 -> |27 63| <- PPU A10<br />
PPU A3 -> |26 62| <- PPU A11<br />
PPU A4 -> |25 61| <- PPU A9<br />
PPU A5 -> |24 60| <- PPU A8<br />
PPU A6 -> |23 59| <- PPU A7<br />
CIRAM A10 <- |22 '''S''' 58| -- '''NC'''<br />
PPU /RD -> |21 57| -- '''NC'''<br />
'''CPU A15''' -> |20 56| <- PPU /WR<br />
'''/SlotIndex3''' -> |19 55| -- '''GND'''<br />
'''/SlotIndex2''' -> |18 54| -- '''GND'''<br />
'''/SlotIndex1''' -> |17 53| -- '''GND'''<br />
'''/SlotIndex0''' -> |16 52| -- '''+5V'''<br />
/IRQ <- |15 51| -- '''+5V'''<br />
CPU R/W -> |14 '''S''' 50| <- /ROMSEL (/A15 + /M2)<br />
CPU A0 -> |13 '''C''' 49| <> CPU D0<br />
CPU A1 -> |12 '''C''' 48| <> CPU D1<br />
CPU A2 -> |11 '''C''' 47| <> CPU D2<br />
CPU A3 -> |10 '''C''' 46| <> CPU D3<br />
CPU A4 -> |09 '''C''' 45| <> CPU D4<br />
CPU A5 -> |08 '''C''' 44| <> CPU D5<br />
CPU A6 -> |07 '''C''' 43| <> CPU D6<br />
CPU A7 -> |06 '''C''' 42| <> CPU D7<br />
CPU A8 -> |05 41| <- CPU A14<br />
CPU A9 -> |04 40| <- CPU A13<br />
CPU A10 -> |03 39| <- CPU A12<br />
CPU A11 -> |02 38| <- M2<br />
GND -- |01 37| -- '''NC'''<br />
-----------<br />
<br />
Notes:<br />
* Signals marked in '''bold''' differ compared to a standard [[Cartridge_connector#Pinout_of_72-pin_NES_consoles_and_cartridges|NES cartridge connector]].<br />
* Signals marked with '''S''' are multiplexed and only sent to the selected slot. (See [[#Slot_select_($5004W)|Slot select ($5004W)]])<br />
* Signals marked with '''C''' are multiplexed and only sent to the selected column. (See [[#Slot_select_($5004W)|Slot select ($5004W)]])<br />
** Column-muxed CPU lines are only enabled when /ROMSEL is asserted.<br />
** Column-muxed PPU lines are only enabled when /PA13 is asserted.<br />
* All non-multiplexed signals are sent to all 16 cartridge slots.<br />
* The FamicomBox leaves system clock (pin 37), CIRAM /CE (pin 57), and PPU /A13 (pin 58) not connected.<br />
<br />
Signal descriptions:<br />
* '''/SlotIndex3..0''': These are fixed to +5V or GND to produce an index matching the ones used in register $5004W. /SlotIndex0 on slot 2 and /SlotIndex1 on slot 4 are floating instead of grounded.<br />
<br />
===15P expand (RP-1)===<br />
This is a [[Expansion port#Famicom|Famicom expansion port]]. The SOUND output is 'audio to RF', with everything already mixed in.<br />
<br />
===25P expand (RP-2)===<br />
SSS-Interface<br />
DB-25<br />
/\<br />
| \<br />
+5V -- | 01 \<br />
| 14 | ?? /IRQ<br />
$5004R /D0 <- | 02 |<br />
| 15 | -> $5004R /D1<br />
$5004R /D2 <- | 03 |<br />
| 16 | -> $5004R /D3<br />
$5004R /D4 <- | 04 |<br />
| 17 | -> $5004R /D5<br />
$5004R /D6 <- | 05 |<br />
| 18 | -> $5004R /D7<br />
$5006W D0 -> | 06 |<br />
| 19 | <- $5006W D1<br />
$5006W D2 -> | 07 |<br />
| 20 | <- $5006W D3<br />
$5006W D4 -> | 08 |<br />
| 21 | <- $5006W D5<br />
$5006W D6 -> | 09 |<br />
| 22 | <- $5006W D7<br />
GND -- | 10 |<br />
| 23 | -- GND<br />
GND -- | 11 |<br />
| 24 | -> M2<br />
GND -- | 12 |<br />
| 25 | -- GND<br />
GND -- | 13 /<br />
| /<br />
\/<br />
<br />
===CATV interface terminal (RP-3)===<br />
SSS-Interface<br />
8| -> Energized<br />
7| -> Game Active<br />
6| <- Billing Clear<br />
5| -> +5v (not used)<br />
+-4| <- GND<br />
| 3| -> Billing Authorized latch<br />
| 2| <- +6.3v<br />
+-1| <> Operation On latch<br />
<br />
All signals active low.<br />
<br />
Pins 1 and 4 are jumpered together.<br />
<br />
See [[#CATV_interface|CATV interface]] for details.<br />
<br />
'''Signal descriptions''':<br />
* '''Operation On latch''': This is tied to the pin 4 GND input by the FamicomBox and thus can be used by both the FamicomBox and external system to detect a connection. If this is not asserted, the FamicomBox can assume that billing is no longer being tracked, so it can trigger an exception and the menu software can prevent further play until asserted again.<br />
* '''Billing Authorized latch''': This outputs the state of the Billing Authorized relay.<br />
* '''GND''': This is only used for the Operation On latch and thus can be used as a meaningful input to prevent the FamicomBox from allowing gameplay.<br />
* '''Billing Clear''': This clears the Billing Authorized relay and puts the console into [[#TV_and_Game_modes|TV mode]]. A 75 ms pulse is required to reliably clear the relay.<br />
* '''Game Active''': This indicates a game is currently being played. It is controlled by the menu software. The external system can use this for billing.<br />
* '''Energized''': This indicates the FamicomBox is operating correctly. It is controlled by the menu software. It requires both system operation and [[#Zapper_detection|successful detection of a Zapper]].<br />
<br />
===DC in connector (RP-5)===<br />
SSS-Interface<br />
+---+<br />
| 1 | -- GND<br />
| 2 | -- +5V<br />
| 3 | -- GND<br />
+---+<br />
<br />
===Expansion connector (P4)===<br />
|SSS-CPU|<br />
-------<br />
+5V -- |01 26| -> $5007W /enable<br />
+5V -- |02 27| -> $5006R /OE<br />
+5V -- |03 28| -> $5005R /OE<br />
M2 <- |04 29| -- +5V<br />
audio mix input -> |05 30| -- +5V<br />
+5V -- |06 31| -- +5V<br />
CPU A6 <- |07 32| -> CPU A7<br />
CPU A4 <- |08 33| -> CPU A5<br />
CPU A2 <- |09 34| -> CPU A3<br />
CPU A0 <- |10 35| -> CPU A1<br />
CPU D1 <> |11 36| <> CPU D0<br />
CPU D3 <> |12 37| <> CPU D2<br />
CPU D5 <> |13 38| <> CPU D4<br />
CPU D7 <> |14 39| <> CPU D6<br />
CPU R/W <- |15 40| -> /$5000-5FFF<br />
CPU audio out 1 <- |16 41| ?? /IRQ<br />
joypad 2 D5 -> |17 42| -> CPU audio out 2<br />
joypad 2 D7 -> |18 43| <- joypad 2 D6<br />
joypad 1 D5 -> |19 44| <- joypad 1 D2<br />
joypad 1 D7 -> |20 45| <- joypad 1 D6<br />
$5007R /D3 -> |21 46| -- GND<br />
$5007R /D6 -> |22 47| -- GND<br />
$5005W D5 <- |23 48| -- GND<br />
GND -- |24 49| -- GND<br />
GND -- |25 50| -- GND<br />
-------<br />
<br />
===Joypad port 1 (FP-2)===<br />
SSS-REL<br />
-<br />
GND -- |1 \<br />
joypad 1 /OE <- |2 5| -- +5V<br />
OUT0 <- |3 6| <- joypad 1 D3<br />
joypad 1 D0 -> |4 7| <- joypad 1 D4<br />
---<br />
<br />
===Joypad port 2 (FP-3)===<br />
SSS-REL<br />
-<br />
GND -- |1 \<br />
joypad 2 /OE <- |2 5| -- +5V<br />
OUT0 <- |3 6| <- joypad 2 D3<br />
joypad 2 D0 -> |4 7| <- joypad 2 D4<br />
---<br />
<br />
* Joypad 2 D3 and D4 can be disabled via DIP switch 10.<br />
<br />
===Joypad port 3 (FP-4)===<br />
SSS-REL<br />
-<br />
joypad port 3 GND -- |1 \<br />
NC -- |2 5| -- +5V<br />
OUT0 <- |3 6| <- joypad 2 D3<br />
NC -- |4 7| <- joypad 2 D4<br />
---<br />
<br />
* This port is intended for use with the Zapper.<br />
* Joypad port 3 GND is the ground signal controlled by $5005W D2. When this is disabled, it instead has a weak pulldown, and the line is expected to be pulled up by the attached controller.<br />
* Joypad 2 D3 and D4 can be disabled via DIP switch 10.<br />
<br />
===Coin box connector (FP-7)===<br />
SSS-REL<br />
1 <- /coin switch<br />
2 -- GND<br />
3 -> coin LED<br />
<br />
Signal descriptions:<br />
* '''coin LED''': This is controlled by the 3199 coin timer's /NEF and /ACT outputs. If /ACT is 0, then LED is /NEF, and otherwise, LED is 0.<br />
<br />
===Coin box power connector (P8)===<br />
SSS-REL<br />
1 -- +5V<br />
2 -- GND<br />
<br />
If using coin box model CTB-370S, 5V is needed for the credit counter. The coin box's 5V input comes from this connector, and its ground input is tied to both FP-7 and P8. With the counterless CTB-370N coin box, this connector is not used.<br />
<br />
==Pinouts (internal)==<br />
===SSS-SOB connector (P1)===<br />
SSS-SOB |SSS-CPU| SSS-SOB<br />
-------<br />
+5V -- |01 37| -- +5V<br />
+5V -- |02 38| -> PPU A13[15]<br />
/ROMSEL[15] <- |03 39| -> PPU A13[14]<br />
/ROMSEL[14] <- |04 40| -> PPU A13[13]<br />
/ROMSEL[13] <- |05 41| -> PPU A13[12]<br />
/ROMSEL[12] <- |06 42| -> PPU A13[11]<br />
/ROMSEL[11] <- |07 43| -> PPU A13[10]<br />
/ROMSEL[10] <- |08 44| -> PPU A13[9]<br />
/ROMSEL[9] <- |09 45| -> PPU A13[8]<br />
/ROMSEL[8] <- |10 46| -> PPU A13[7]<br />
/ROMSEL[7] <- |11 47| -> PPU A13[6]<br />
/ROMSEL[6] <- |12 48| -> PPU A13[5]<br />
/ROMSEL[5] <- |13 49| -> PPU A13[4]<br />
/ROMSEL[4] <- |14 50| -> PPU A13[3]<br />
/ROMSEL[3] <- |15 51| -> PPU A13[2]<br />
/ROMSEL[2] <- |16 52| -> PPU A13[1]<br />
/ROMSEL[1] <- |17 53| -> PPU /WR<br />
PPU /RD <- |18 54| -> CPU R/W<br />
CIC CLK (3.58 MHz) <- |19 55| -> guest CIC reset<br />
CIC toPak <- |20 56| -> PPU A0<br />
PPU A12 <- |21 57| -> PPU A1<br />
PPU A10 <- |22 58| -> PPU A2<br />
PPU A11 <- |23 59| -> PPU A3<br />
PPU A9 <- |24 60| -> PPU A4<br />
PPU A8 <- |25 61| -> PPU A5<br />
PPU A7 <- |26 62| -> PPU A6<br />
CPU A0 <- |27 63| -> CPU A1<br />
CPU A2 <- |28 64| -> CPU A3<br />
CPU A4 <- |29 65| -> CPU A5<br />
CPU A6 <- |30 66| -> CPU A7<br />
CPU A14 <- |31 67| -> CPU A8<br />
CPU A13 <- |32 68| -> CPU A9<br />
CPU A12 <- |33 69| -> CPU A10<br />
M2 <- |34 70| -> CPU A11<br />
CIC toMB -> |35 71| -- GND<br />
GND -- |36 72| -- GND<br />
-------<br />
<br />
Numbers in brackets indicate slot or column indexes for multiplexed signals. The signals here that are duplicated on P3 are behind a separate ALS541 buffer.<br />
<br />
===SSS-SOB connector (P2)===<br />
SSS-SOB |SSS-CPU| SSS-SOB<br />
-------<br />
+5V -- |01 37| -- +5V<br />
+5V -- |02 38| -- +5V<br />
CIRAM A10[15] -> |03 39| <- CIRAM A10[14]<br />
CIRAM A10[13] -> |04 40| <- CIRAM A10[12]<br />
CIRAM A10[11] -> |05 41| <- CIRAM A10[10]<br />
CIRAM A10[9] -> |06 42| <- CIRAM A10[8]<br />
CIRAM A10[7] -> |07 43| <- CIRAM A10[6]<br />
CIRAM A10[5] -> |08 44| <- CIRAM A10[4]<br />
CIRAM A10[3] -> |09 45| <- CIRAM A10[2]<br />
CIRAM A10[1] -> |10 46| <> PPU D4[3]<br />
PPU D3[3] <> |11 47| <> PPU D5[3]<br />
PPU D2[3] <> |12 48| <> PPU D6[3]<br />
PPU D1[3] <> |13 49| <> PPU D7[3]<br />
PPU D0[3] <> |14 50| <> CPU D0[3]<br />
CPU D1[3] <> |15 51| <> CPU D2[3]<br />
CPU D3[3] <> |16 52| <> CPU D4[3]<br />
CPU D5[3] <> |17 53| <> CPU D6[3]<br />
CPU D7[3] <> |18 54| <> PPU D4[2]<br />
PPU D3[2] <> |19 55| <> PPU D5[2]<br />
PPU D2[2] <> |20 56| <> PPU D6[2]<br />
PPU D1[2] <> |21 57| <> PPU D7[2]<br />
PPU D0[2] <> |22 58| <> CPU D0[2]<br />
CPU D1[2] <> |23 59| <> CPU D2[2]<br />
CPU D3[2] <> |24 60| <> CPU D4[2]<br />
CPU D5[2] <> |25 61| <> CPU D6[2]<br />
CPU D7[2] <> |26 62| <> PPU D4[1]<br />
PPU D3[1] <> |27 63| <> PPU D5[1]<br />
PPU D2[1] <> |28 64| <> PPU D6[1]<br />
PPU D1[1] <> |29 65| <> PPU D7[1]<br />
PPU D0[1] <> |30 66| <> CPU D0[1]<br />
CPU D1[1] <> |31 67| <> CPU D2[1]<br />
CPU D3[1] <> |32 68| <> CPU D4[1]<br />
CPU D5[1] <> |33 69| <> CPU D6[1]<br />
CPU D7[1] <> |34 70| -- GND<br />
GND -- |35 71| -- GND<br />
GND -- |36 72| -- GND<br />
-------<br />
<br />
Numbers in brackets indicate slot or column indexes for multiplexed signals.<br />
<br />
===SSS-SOB connector (P3)===<br />
SSS-SOB |SSS-CPU| SSS-SOB<br />
-------<br />
+5V -- |01 37| -- +5V <br />
+5V -- |02 38| -- +5V<br />
LED /S3 <- |03 39| -- +5V<br />
LED /S4 <- |04 40| -- +5V<br />
LED /S5 <- |05 41| -- +5V<br />
LED /S6 <- |06 42| -- +5V<br />
LED /S7 <- |07 43| -- +5V<br />
GND -- |08 44| -- GND<br />
GND -- |09 45| -- GND<br />
LED /S0 <- |10 46| -- GND<br />
LED /S1 <- |11 47| -- GND<br />
LED /S2 <- |12 48| -- GND<br />
LED C0 <- |13 49| -- GND<br />
LED C1 <- |14 50| -- GND<br />
GND -- |15 51| -- GND<br />
GND -- |16 52| -- GND<br />
GND -- |17 53| -- GND<br />
/IRQ -> |18 54| -> PPU /WR<br />
PPU /RD <- |19 55| -> CPU R/W<br />
PPU A0 <- |20 56| -> PPU A12<br />
PPU A1 <- |21 57| -> PPU A11<br />
PPU A2 <- |22 58| -> PPU A10<br />
PPU A3 <- |23 59| -> PPU A9<br />
PPU A4 <- |24 60| -> PPU A8<br />
PPU A5 <- |25 61| -> PPU A7<br />
PPU A6 <- |26 62| -> CPU A0<br />
CPU A1 <- |27 63| -> CPU A2<br />
CPU A3 <- |28 64| -> CPU A4<br />
CPU A5 <- |29 65| -> CPU A6<br />
CPU A7 <- |30 66| -> CPU A14<br />
CPU A8 <- |31 67| -> CPU A13<br />
CPU A9 <- |32 68| -> CPU A12<br />
CPU A10 <- |33 69| -> M2<br />
CPU A11 <- |34 70| -- GND<br />
CPU A15 <- |35 71| -- GND<br />
GND -- |36 72| -- GND<br />
-------<br />
<br />
Numbers in brackets indicate slot or column indexes for multiplexed signals. The signals here that are duplicated on P1 are behind a separate ALS541 buffer.<br />
<br />
Signal descriptions:<br />
* '''LED /S0..7''': These select a slot LED. Only one of these is asserted at a time (unless flashing is enabled, which disables all of them half the time). The active line is selected by $5002W D2..0.<br />
* '''LED C0..1''': These select a slot LED channel and have opposite values. LC1 is $5002W D3 and LC0 the inverse.<br />
<br />
===RF modulator connector (P5)===<br />
SSS-CPU<br />
+---+<br />
| 1 | -> TV/GAME<br />
| 2 | -- +5V<br />
| 3 | -> VIDEO<br />
| 4 | -> 40% on<br />
| 5 | -- GND<br />
| 6 | -> audio to RF<br />
| 7 | -- GND<br />
+---+<br />
<br />
Signal descriptions:<br />
* '''TV/GAME''': When high, passes RF input through to RF output. The RF modulator pulls this low (via pin 5).<br />
* '''40% on''': When high, reduces screen brightness to approximately 45%.<br />
<br />
===SSS-Interface connector (P6 / RP-4)===<br />
SSS-Interface |SSS-CPU| SSS-Interface<br />
-------<br />
+5V -- |01 31| -- GND<br />
+5V -- |02 32| -- GND<br />
+5V -- |03 33| -- GND<br />
+5V -- |04 34| -- GND<br />
+5V -- |05 35| -- GND<br />
joypad 1 D0 xx |06 36| <- joypad ports 2 and 3 D3 and D4 disable<br />
$5002R /D7 -> |07 37| <- $5002R /D6<br />
$5002R /D5 -> |08 38| <- $5002R /D4<br />
$5002R /D3 -> |09 39| <- $5002R /D2<br />
$5002R /D1 -> |10 40| <- $5002R /D0<br />
joypad 1 /OE <- |11 41| xx joypad 2 D0<br />
joypad 1 D1 <- |12 42| <- joypad 2 D1<br />
OUT0 <- |13 43| <- joypad 2 D2<br />
OUT1 <- |14 44| xx joypad 2 D3<br />
OUT2 <- |15 45| xx joypad 2 D4<br />
joypad 2 /OE <- |16 46| ?? /IRQ<br />
M2 <- |17 47| -> audio to RF<br />
beep disable <- |18 48| -- GND<br />
$5006W D7 <- |19 49| -- GND<br />
$5006W D5 <- |20 50| -> $5006W D6<br />
$5006W D3 <- |21 51| -> $5006W D4<br />
$5006W D1 <- |22 52| -> $5006W D2<br />
$5004R /D7 -> |23 53| <- $5004W D0<br />
$5004R /D5 -> |24 54| <- $5004R /D6<br />
$5004R /D3 -> |25 55| <- $5004R /D4<br />
$5004R /D1 -> |26 56| <- $5004R /D2<br />
CATV pin 7 -> |27 57| <- $5004R /D0<br />
CATV pin 6 -> |28 58| <- CATV pin 8<br />
CATV pin 3 -> |29 59| -- GND<br />
CATV pin 1 -> |30 60| <- CATV pin 2<br />
-------<br />
<br />
Signal descriptions:<br />
* '''beep disable''': This disables the near-end flash beeping controlled by the 3199 coin timer. SSS-Interface connects this to DIP switch 9.<br />
* '''joypad ports 2 and 3 D3 and D4 disable''': This disables D3 and D4 just on joypad ports 2 and 3. They can still be used over the Famicom expansion port. SSS-Interface connects this to DIP switch 10.<br />
* '''audio to RF''': This is the same audio sent to the RF modulator (with everything mixed in), but here is used for the Famicom expansion port.<br />
* '''CATV pin 6..8''': These are referred to in the schematic as CA5..7.<br />
<br />
===SSS-REL connector (P7 / FP-1)===<br />
SSS-REL |SSS-CPU| SSS-REL<br />
-------<br />
+5V -- |01 14| -> OUT0<br />
+5V -- |02 15| <- joypad 2 D4<br />
TV/GAME LED <- |03 16| <- joypad 2 D3<br />
TV/GAME button -> |04 17| <- joypad 1 D3<br />
/reset button -> |05 18| <- joypad 1 D4<br />
TV/GAME button enable <- |06 19| <- /keyswitch position 0<br />
coin LED <- |07 20| <- /keyswitch position 1<br />
/COIN -> |08 21| <- /keyswitch position 2<br />
joypad port 3 GND <> |09 22| <- /keyswitch position 3<br />
joypad 1 D0 -> |10 23| <- /keyswitch position 4<br />
joypad 2 D0 -> |11 24| <- /keyswitch position 9<br />
joypad 1 /OE <- |12 25| -- GND<br />
joypad 2 /OE <- |13 26| -- GND<br />
--------<br />
<br />
This connector differs from the SSS-CPU schematic on manual page 48 in size, signal pin numbers, and signal names. The connector as shown on page 49 is accurate (except that pins 15 and 16 are reversed).<br />
<br />
Signal descriptions:<br />
* '''TV/GAME LED''': This is used to indicate game mode (high to light LED).<br />
* '''TV/GAME button enable''': This is connected to +5V on the SSS-CPU (but incorrectly shown on the schematic as controlled by a register).<br />
* '''/COIN''': This connects to the 3199 coin timer and is driven low by either the coin box's coin switch, or by the SSS-REL's service button.<br />
* '''joypad port 3 GND''': This is driven low by SSS-CPU to enable joypad port 3, or instead weakly pulled low so the Zapper can pull it high, in which case it's an input to the SSS-CPU.<br />
* '''/keyswitch position 0..4, 9''': These are pulled high on the SSS-CPU.<br />
<br />
===SSS-LED connector (P19)===<br />
SSS-SOB SSS-LED<br />
+---+<br />
| 1 | -> LED C0<br />
| 2 | -> LED C0<br />
| 3 | -> LED /S5<br />
| 4 | -> LED /S4<br />
| 5 | -> LED /S3<br />
| 6 | -> LED /S2<br />
| 7 | -> LED /S1<br />
+---+<br />
<br />
===SSS-LED connector (P20)===<br />
SSS-SOB SSS-LED<br />
+---+<br />
| 1 | -> LED C0<br />
| 2 | -> LED C1<br />
| 3 | -> LED /S2<br />
| 4 | -> LED /S1<br />
| 5 | -> LED /S0<br />
| 6 | -> LED /S7<br />
| 7 | -> LED /S6<br />
+---+<br />
<br />
LED C0 enables LED /S6..7 and LED C1 enables LED /S0..2.<br />
<br />
===SSS-LED connector (P21)===<br />
SSS-SOB SSS-LED<br />
+---+<br />
| 1 | -> LED C1<br />
| 2 | -> LED C1<br />
| 3 | -> LED /S7<br />
| 4 | -> LED /S6<br />
| 5 | -> LED /S5<br />
| 6 | -> LED /S4<br />
| 7 | -> LED /S3<br />
+---+<br />
<br />
===SSS-SW connector (FP-5)===<br />
SSS-REL<br />
+---+<br />
| 1 | -- GND<br />
| 2 | <- /reset button<br />
| 3 | <- TV/GAME button<br />
| 4 | -> TV/GAME button enable<br />
| 5 | -> TV/GAME LED<br />
+---+<br />
<br />
===Keyswitch (FP-6)===<br />
SSS-REL<br />
+---+<br />
| 1 | <- /keyswitch position 0<br />
| 2 | <- /keyswitch position 1<br />
| 3 | <- /keyswitch position 2<br />
| 4 | <- /keyswitch position 3<br />
| 5 | <- /keyswitch position 4<br />
| 6 | -- GND<br />
| 7 | <- /keyswitch position 9<br />
+---+<br />
<br />
===3198A CIC lockout===<br />
-------------------<br />
Data out <- | 1 R0.0 VDD 16 | -- +5V<br />
Data in -> | 2 R0.1 R2.2 15 | <- Slot select D3 ($5004W D3)<br />
Seed -> | 3 R0.2 R2.1 14 | <- Slot select D2 ($5004W D2)<br />
Host/Guest -> | 4 R0.3 R2.0 13 | -- NC<br />
NC -- | 5 R3.3 R1.3 12 | <- Slot select D1 ($5004W D1)<br />
/3.58 MHz clock -> | 6 CL1 R1.2 11 | <- Slot select D0 ($5004W D0)<br />
Exception reset -> | 7 ACL R1.1 10 | -> Guest CIC reset<br />
GND -- | 8 GND R1.0 9 | -> /Host reset<br />
-------------------<br />
<br />
* When the 3198 triggers a host reset, it does so just once, allowing the menu software to regain control of the system and skip over any slot that may have triggered the reset.<br />
* On guest CICs, the slot select D3..0 inputs use SlotIndex3..0.<br />
<br />
===3199A coin timer ===<br />
-------------------<br />
TS0 ($5001W D0) -> | 1 R0.0 VDD 16 | -- +5V<br />
TS1 ($5001W D1) -> | 2 R0.1 R2.2 15 | <- /COIN (/coin switch)<br />
TS2 ($5001W D2) -> | 3 R0.2 R2.1 14 | <- CH ($5001W D5)<br />
CC0 ($5001W D3) -> | 4 R0.3 R2.0 13 | -> /NEF (/near-end flash)<br />
ACTE (active exception) <- | 5 R3.3 R1.3 12 | <- CC1 ($5001W D4)<br />
/3.58 MHz clock -> | 6 CL1 R1.2 11 | <- NMI/2<br />
POC (reset) -> | 7 ACL R1.1 10 | -> /NE (/near end)<br />
GND -- | 8 GND R1.0 9 | -> /ACT (/active)<br />
-------------------<br />
<br />
Signal descriptions:<br />
* '''ACTE''': This controls the credit transition exception. It is believed to be a pulse when switching either way between having and not having credit.<br />
* '''/ACT''': This indicates the coin timer is active (has play time credit). The menu software uses this to know there is credit.<br />
* '''/NE''': This indicates low time remaining.<br />
* '''/NEF''': This controls the low-time beeping, screen dimming, and coin-box LED flashing.<br />
* '''NMI/2''': This alternates every NMI. It appears to control the /NEF timing.<br />
* '''TS1-0''': These control time per coin. %01 sets 10 minutes and %10 sets 15 minutes. It is not known what other configurations do.<br />
* '''TS2''': Behavior is unknown, but this is set to 0 by the menu software when setting TS1-0 and may be another time-per-coin control.<br />
* '''CH''': Behavior is unknown, but according to the partial ROM dump, this has some effect when the coin timer sets /ACT to 0 and /NE to 1. Menu software sets this to 1 when configuring time-per-coin. Speculation is that this may tell the coin timer to run the timer ("charge").<br />
<br />
==Schematic errata==<br />
* P7 should be a 26-pin connector, not a 40-pin connector. All of the signals shown on the 40-pin version are still present, but numbering and naming differ slightly.<br />
* P7 $4017 D3 and D4 pin names should be swapped.<br />
* P4 pin 10 should be labeled A0.<br />
* FP-1 pin 1 should be labeled GND.<br />
* The LS3 input to LC0 and LC1 on P3 pins 13 and 14 should be labeled LE3.<br />
* The 4040 12-bit counter for dividing the clock should have a tap on Q9, producing a 0.85 Hz clock. The watchdog should be clocked by this.<br />
* For the PA13 signal coming out of the ALS541 by the PPU, /PA13 goes to the TM2215 CIRAM as pictured, but the signal to the LS139 and ALS138's should be PA13 (does not go through the inverter).<br />
* Instead of $5005W D4 controlling P7 pin 6 (TV/GAME switch enable), $5005W D4 should be not connected and the switch enable should be tied to +5V on the main board.<br />
* Instead of $5005W D5 acting as a TV mode enable by connecting to the TV/GAME mode SR latch, it should instead connect to $5007R /D7 and expansion connector (P4) pin 23. This makes pin 23 an output.<br />
<br />
==Hardware configurations==<br />
* Main board:<br />
** SSS-CPU-02<br />
** SSS-CPU-03<br />
*** The PCB traces are wired so that the joypad button press exception's two 4021 shift registers, which implement the read counts, are each used for the wrong joypad. This was fixed at the factory by cutting the joypad /OE traces between the HC257 muxer and shift registers and adding wires to swap the connections.<br />
** SSS-CPU-04<br />
* Chipsets:<br />
** RP2A03E / RP2C02E-0<br />
** RP2A03G / RP2C02G-0</div>Fiskbithttps://www.nesdev.org/w/index.php?title=EXP_pins&diff=21693EXP pins2024-03-25T08:20:10Z<p>Fiskbit: Adds Broke Studio boards. Makes a small change to the ATtiny13 programming description for clarity.</p>
<hr />
<div>The [[EXP pins]] are expansion pins present on the 72-pin NES cartridge connector and which connect to the expansion port on the bottom of the NES-001 console. These pins were not used by any officially released consumer device, but are used by various unlicensed devices and the [[FamicomBox]] hotel console.<br />
<br />
==Pin summary==<br />
{| class="wikitable"<br />
|-<br />
! <br />
!EXP0<br />
!EXP1<br />
!EXP2<br />
!EXP3<br />
!EXP4<br />
!EXP5<br />
!EXP6<br />
!EXP7<br />
!EXP8<br />
!EXP9<br />
|-<br />
!style="text-align: left"|[[#Broke_Studio_discrete_mapper_cartridges|Broke Studio discrete mapper cartridges]]<br />
|style="text-align: center"|✓<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|✓<br />
|<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[#Broke_Studio_MMC_mapper_cartridges|Broke Studio MMC mapper cartridges]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|-<br />
!style="text-align: left"|[[#Broke_Studio_Rainbow_mapper_cartridges|Broke Studio Rainbow mapper cartridges]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|-<br />
!style="text-align: left"|[[#CopyNES|CopyNES]]<br />
|style="text-align: center"|✓<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[Everdrive N8]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[Everdrive N8 Pro]]<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|-<br />
!style="text-align: left"|[[#Expansion_Port_Sound_Module_(EPSM)|Expansion Port Sound Module (EPSM)]]<br />
|<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|-<br />
!style="text-align: left"|[[#ExROM_(MMC5)|ExROM (MMC5)]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[#Extended_NES_I/O_(ENIO)|Extended NES I/O (ENIO)]]<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|-<br />
!style="text-align: left"|[[#Famicom-to-NES_adapter|Famicom-to-NES adapter]]<br />
|<br />
|<br />
|style="text-align: center"|♪*<br />
|<br />
|<br />
|<br />
|style="text-align: center"|♪*<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[#FamicomBox|FamicomBox]]<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|-<br />
!style="text-align: left"|[[#INL_cartridges|INL cartridges]]<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|✓*<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|<br />
|style="text-align: center"|<br />
|style="text-align: center"|♪<br />
|-<br />
!style="text-align: left"|[[#INL_Expansion_Audio_Dongle_Slim|INL Expansion Audio Dongle Slim]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|style="text-align: center"|~<br />
|-<br />
!style="text-align: left"|[[#Muramasa_NES_FDS|Muramasa NES FDS]]<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|-<br />
!style="text-align: left"|[[#NES-21G-CPU-72P|NES-21G-CPU-72P]]<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|✓<br />
|-<br />
!style="text-align: left"|[[#PowerPak|PowerPak]]<br />
|style="text-align: center"|✓<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|style="text-align: center"|♪<br />
|style="text-align: center"|~<br />
|style="text-align: center"|~<br />
|<br />
|-<br />
!style="text-align: left"|[[#PowerPak_Lite|PowerPak Lite]]<br />
|style="text-align: center"|✓<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|-<br />
!style="text-align: left"|[[#Simple_Famicom_Expansion_Audio_Module_(SFEAM)|Simple Famicom Expansion Audio Module (SFEAM)]]<br />
|<br />
|<br />
|style="text-align: center"|♪*<br />
|<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|style="text-align: center"|♪*<br />
|-<br />
!style="text-align: left"|[[TinyNES]]<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|style="text-align: center"|♪<br />
|<br />
|<br />
|<br />
|}<br />
✓ : This pin is used.<br/><br />
♪ : This pin is used for expansion audio output (cartridge) or input (expansion device or console).<br/><br />
<nowiki>*</nowiki> : This pin is used by some, but not all such devices.<br/><br />
<nowiki>~</nowiki> : This pin is connected, but lacks a specific function.<br />
<br />
==Pin notes==<br />
===EXP0===<br />
Some modern cartridges have been observed that connect EXP0 to ground, likely because of the presence of a ground pin on the Famicom's cartridge connector in the region where the EXP pins are placed on the NES'. This provides no meaningful benefit and adds risk. For example, inserting such a cartridge into the FamicomBox can short 5V to ground through this pin, causing damage to the cartridge or console.<br />
===EXP2===<br />
EXP2 is not present on the NES-101.<br />
===EXP3===<br />
EXP3 is not present on the NES-101.<br />
===EXP5===<br />
EXP5 is not present on the NES-101.<br />
===EXP6===<br />
EXP6 is not present on the NES-101. It has become the standard console input for expansion audio and is used by flash carts, modern homebrew, and modern Famicom-to-NES adapters.<br />
===EXP9===<br />
Because EXP6 is not present on the NES-101, some NES-101 users have modified cartridges to send expansion audio over EXP9, instead.<br />
<br />
==Devices==<br />
===Broke Studio discrete mapper cartridges===<br />
Broke Studio's NROM, BNROM, and UNROM512 boards use EXP0 and EXP5 for programming and ROM and CIC, respectively.<br />
<br />
Programmer | Cart | Programmer<br />
-----------------<br />
...<br />
|20 EXP4<br />
|19 EXP3 EXP5 55| <- ATtiny13 AVR reset<br />
|18 EXP2 EXP6 54|<br />
|17 EXP1 EXP7 53|<br />
PRG-ROM /WE -> |16 EXP0 EXP8 52|<br />
EXP9 51|<br />
...<br />
<br />
===Broke Studio MMC mapper cartridges===<br />
Broke Studio's MMC board uses EXP5 for programming the CIC and outputs expansion audio on both EXP6 and EXP9. These audio outputs are tied together.<br />
<br />
Programmer or Programmer or<br />
Expansion port | Cart | Expansion Port<br />
-----------------<br />
...<br />
|20 EXP4<br />
|19 EXP3 EXP5 55| <- ATtiny13 AVR reset<br />
|18 EXP2 EXP6 54| -> audio<br />
|17 EXP1 EXP7 53|<br />
|16 EXP0 EXP8 52|<br />
EXP9 51| -> audio<br />
...<br />
<br />
===Broke Studio Rainbow mapper cartridges===<br />
Broke Studio's Rainbow mapper board uses EXP5 for programming the CIC and is capable of outputting ''different'' expansion audio on each of EXP6 and EXP9. The Rainbow mapper itself produces just one audio stream, which software can choose to output on either or both of these pins. However, the cartridge pins connect to separate FPGA pins, and so another mapper implemented on the same board could output unique audio on each.<br />
<br />
Programmer or Programmer or<br />
Expansion port | Cart | Expansion Port<br />
-----------------<br />
...<br />
|20 EXP4<br />
|19 EXP3 EXP5 55| <- ATtiny13 AVR reset<br />
|18 EXP2 EXP6 54| -> audio 1<br />
|17 EXP1 EXP7 53|<br />
|16 EXP0 EXP8 52|<br />
EXP9 51| -> audio 2<br />
...<br />
<br />
===CopyNES===<br />
The [[CopyNES]] allows the 2A03 to control EXP0. It's used to write to RAM carts, such as the PowerPak Lite.<br />
<br />
===Expansion Port Sound Module (EPSM)===<br />
The [[EPSM]] can be written through either a cart-agnostic universal access mode or a mapper-specific mode, where the cartridge decodes the address and passes chip enable and address bits via EXP pins. It also accepts expansion audio input on EXP2, EXP6, and EXP9, to support as wide a variety of cartridges as possible.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
YMF288 A1 <- |20 EXP4<br />
EPSM /CE2 <- |19 EXP3 EXP5 55|<br />
audio <- |18 EXP2 EXP6 54| -> audio<br />
EPSM /CE1 <- |17 EXP1 EXP7 53| -> YMF288 A0<br />
|16 EXP0 EXP8 52| -> EPSM CE3<br />
EXP9 51| -> audio<br />
...<br />
<br />
===ExROM (MMC5)===<br />
ExROM boards, using [[MMC5]], are configured for expansion audio output on EXP6, though the boards must also have the appropriate resistors and capacitors populated for this to function. EXP5, which is pulled low in the cart, is used as a PRG-RAM read disable.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
|20 EXP4<br />
|19 EXP3 EXP5 55| <- PRG-RAM /OE<br />
|18 EXP2 EXP6 54| -> audio<br />
|17 EXP1 EXP7 53|<br />
|16 EXP0 EXP8 52|<br />
EXP9 51|<br />
...<br />
<br />
===Extended NES I/O (ENIO)===<br />
The [[ENIO]] CPU board can be accessed through either a cart-agnostic compatibility mode or a direct addressing mode, where the cartridge decodes the address and passes R/W and /CE to the ENIO via EXP pins. EXP5 and EXP7-9 are passed to the CPU board, handling R/W, /CE, and presumably other currently-undocumented functionality. EXP6 is used as an expansion audio input. EXP0-4 are routed to an unpopulated header for expansion use.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
ENIO J4 header ?? |20 EXP4<br />
ENIO J4 header ?? |19 EXP3 EXP5 55| ?? unknown (ENIO CPU board)<br />
ENIO J4 header ?? |18 EXP2 EXP6 54| -> audio<br />
ENIO J4 header ?? |17 EXP1 EXP7 53| -> ENIO R/W<br />
ENIO J4 header ?? |16 EXP0 EXP8 52| -> ENIO /CE<br />
EXP9 51| ?? unknown (ENIO CPU board)<br />
...<br />
<br />
===Famicom-to-NES adapter===<br />
Some Famicom-to-NES adapters connect expansion audio to an EXP pin. If connected, modern adapters typically use EXP6, though EXP2 has been observed due to its proximity to the audio-to-RF pin on the Famicom cartridge connector.<br />
<br />
===FamicomBox===<br />
The [[FamicomBox]] uses the EXP pins primarily to indicate slot ID to the cartridge's 3198 CIC. 9 of the pins are tied to some combination of ground and 5V, which can cause damage to non-FamicomBox cartridges that use EXP pins. One additional pin provides A15, which is not used by any contemporary game. Unlike the NES-001, the FamicomBox does not route any of these pins to any external port for expansion use.<br />
<br />
FamicomBox | Cart | FamicomBox<br />
-----------------<br />
...<br />
CPU A15 -> |20 EXP4<br />
/SlotIndex3 -> |19 EXP3 EXP5 55| -- GND<br />
/SlotIndex2 -> |18 EXP2 EXP6 54| -- GND<br />
/SlotIndex1 -> |17 EXP1 EXP7 53| -- GND<br />
/SlotIndex0 -> |16 EXP0 EXP8 52| -- +5V<br />
EXP9 51| -- +5V<br />
...<br />
<br />
===INL cartridges===<br />
Infinite NES Lives cartridges use EXP pins for various purposes, though not universally across all boards. EXP6 and EXP9 are used to output expansion audio to the console. Newer boards use EXP0 as PRG-ROM /WE for writing the cartridges, with a pullup on the board. Some boards use EXP0-3 (and EXP4 on dual-CPLD boards) for a JTAG interface. When an ATtiny13 is used for the CIC, EXP5 acts as AVR reset. The ATtiny13 is configured for high voltage power supply (HVPS) programming at 12v.<br />
<br />
Programmer or Programmer or<br />
Expansion port | Cart | Expansion Port<br />
-----------------<br />
...<br />
|20 EXP4<br />
|19 EXP3 EXP5 55|<br />
|18 EXP2 EXP6 54| -> audio<br />
|17 EXP1 EXP7 53|<br />
PRG-ROM /WE -> |16 EXP0 EXP8 52|<br />
EXP9 51| -> audio<br />
...<br />
<br />
Programmer or Programmer or<br />
Expansion port | Cart | Expansion Port<br />
-----------------<br />
...<br />
CPLD2 JTAG TCK -> |20 EXP4<br />
CPLD1 JTAG TCK -> |19 EXP3 EXP5 55| <- ATtiny13 AVR reset<br />
JTAG TMS -> |18 EXP2 EXP6 54| -> audio<br />
JTAG TDI -> |17 EXP1 EXP7 53|<br />
JTAG TDO -> |16 EXP0 EXP8 52|<br />
EXP9 51| -> audio<br />
...<br />
<br />
===INL Expansion Audio Dongle Slim===<br />
This expansion port adapter enables expansion audio input on EXP6. While it only has pins on EXP6 and audio mix input by default, pins can be added to it on EXP9 and audio output, though they aren't routed anywhere on the board. Because EXP6 is the default for expansion audio output and the NES-001 is the only console with this expansion port, connecting to EXP9 is unlikely to be useful.<br />
<br />
===Muramasa NES FDS===<br />
Because the NES-001 doesn't easily allow a cartridge to connect with another device via an external cable, Muramasa's NES FDS connects the RAM adapter cartridge and disk drive via the EXP pins.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
serial out <- |20 EXP4<br />
(R/W) $4034.W2 <- |19 EXP3 EXP5 55| <- serial in<br />
(transfer reset) $4035.W1 <- |18 EXP2 EXP6 54| -> audio<br />
(write protected) $4032.R2 -> |17 EXP1 EXP7 53| -> $4025.W0 (motor control)<br />
(disk /ready) $4032.R1 -> |16 EXP0 EXP8 52| <- $4032.R0 (disk /inserted)<br />
EXP9 51| <- battery<br />
...<br />
<br />
===NES-21G-CPU-72P===<br />
The [[User:Lidnariq/NES-21G-CPU-72P|NES-21G-CPU-72P]] board is used in some Nintendo test cartridges and uses the EXP pins to interact with an unknown device. The last value written to $6000 is outputted over 8 EXP pins, with the high bit also signaling whether the M2 and the system clock inputs are not functioning. EXP6 indicates when $6000 is being read, and it is speculated that this would cause the expansion device to drive the latched data onto the CPU data lines. EXP5 is used, but its effect is currently unknown; it may control the PRG-ROM's /OE.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
$6000.R4 <- |20 EXP4<br />
$6000.R3 <- |19 EXP3 EXP5 55| <- unknown<br />
$6000.R2 <- |18 EXP2 EXP6 54| -> $6000 /read<br />
$6000.R1 <- |17 EXP1 EXP7 53| -> $6000.R7 OR clocks bad<br />
$6000.R0 <- |16 EXP0 EXP8 52| -> $6000.R6<br />
EXP9 51| -> $6000.R5<br />
...<br />
<br />
===NES modem===<br />
The NES modem is an unreleased official expansion device that would have allowed online access. It is highly likely this device uses the EXP pins, but no specifics are known.<br />
<br />
===PowerPak===<br />
The [[PowerPak]] uses EXP0 to allow the CopyNES to program the boot ROM. EXP1-8 are connected to the FPGA and can be used, but only EXP6 has been (for expansion audio output). EXP9 is not connected, and some users have bridged it with EXP6 to enable expansion audio on NES-101 consoles.<br />
<br />
Expansion Port | Cart | Expansion Port<br />
-----------------<br />
...<br />
FPGA pin 22 ?? |20 EXP4<br />
FPGA pin 20 ?? |19 EXP3 EXP5 55| ?? FPGA pin 19<br />
FPGA pin 27 ?? |18 EXP2 EXP6 54| -> audio (FPGA pin 23)<br />
FPGA pin 12 ?? |17 EXP1 EXP7 53| ?? FPGA pin 94<br />
boot ROM program -> |16 EXP0 EXP8 52| ?? FPGA pin 41<br />
EXP9 51|<br />
...<br />
<br />
===PowerPak Lite===<br />
The [[PowerPak Lite]] is programmed with settings for the current game by a CopyNES via EXP0.<br />
<br />
===Simple Famicom Expansion Audio Module (SFEAM)===<br />
This expansion port adapter enables expansion audio input on EXP2, EXP6, or EXP9. It comes with a resistor populated only for EXP6 audio, leaving EXP2 and EXP9 disconnected by default.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=6502_assembly_optimisations&diff=216706502 assembly optimisations2024-03-18T21:06:49Z<p>Fiskbit: /* Avoiding the need for CLC/SEC with ADC/SBC */ If carry is clear, SBC should use value-1, not value+1. Thanks to Ooxie for reporting.</p>
<hr />
<div>This page is about optimisations that are possible in assembly language, or various things one programmer has to keep in mind to make their code as optimal as possible.<br />
<br />
There is two major kind of optimisations: Optimisation for speed (code executes in fewer cycles) and optimisation for size (the code takes fewer bytes).<br />
<br />
There is also some other kinds of optimisations, such as constant-executing-time optimisation (code execute in a constant number of cycle no matter what it has to do), or RAM usage optimisation (use as few variables as possible).<br />
Because those optimisations have more to do with the algorithm than with its implementation in assembly, only speed and size optimisations will be discussed in this article.<br />
<br />
== Optimise both speed and size of the code ==<br />
<br />
=== Avoid a jsr + rts chain ===<br />
<br />
<span id="Tail call"></span>A [[wikipedia:tail call|tail call]] occurs when a subroutine finishes by calling another subroutine. This can be optimised into a JMP instruction:<br />
<br />
<pre><br />
MySubroutine<br />
lda Foo<br />
sta Bar<br />
jsr SomeRandomRoutine<br />
rts<br />
</pre><br />
<br />
becomes :<br />
<br />
<pre><br />
MySubroutine<br />
lda Foo<br />
sta Bar<br />
jmp SomeRandomRoutine<br />
</pre><br />
<br />
Savings : 9 cycles, 1 byte<br />
<br />
=== Split word tables in high and low components ===<br />
<br />
This optimisation is not human friendly, makes the source code much bigger, but still makes the compiled<ref name="compile_pedantry">Pedants may complain that "compile" is incorrect terminology for "translate a program written in assembly language into object code". But it is the most familiar term meaning "translate a program, no matter the language, into object code", and the same issues apply to code generators within a compiler that targets the 6502 as to programs written in 6502 assembly language.</ref> size smaller and faster:<br />
<br />
<pre><br />
Example<br />
lda FooBar<br />
asl A<br />
tax<br />
lda PointerTable,X<br />
sta Temp<br />
lda PointerTable+1,X<br />
sta Temp+1<br />
....<br />
<br />
PointerTable<br />
.dw Pointer1, Pointer2, ....<br />
</pre><br />
<br />
Becomes :<br />
<br />
<pre><br />
Example<br />
ldx FooBar<br />
lda PointerTableL,X<br />
sta Temp<br />
lda PointerTableH,X<br />
sta Temp+1<br />
....<br />
<br />
PointerTableL<br />
.byt <Pointer1, <Pointer2, ....<br />
<br />
PointerTableH<br />
.byt >Pointer1, >Pointer2, ....<br />
</pre><br />
<br />
Some assemblers may have a way to implement a macro to automatically make the table coded like this (Unofficial MagicKit Assembler is one such program).<br />
<br />
Savings : 2 bytes, 4 cycles<br />
<br />
=== Use Jump tables with RTS instruction instead of JMP indirect instruction ===<br />
<br />
<span id="RTS Trick"></span>The so-called [[RTS Trick]] is a method of implementing jump tables by pushing a subroutine's entry point to the stack.<br />
<br />
<pre><br />
; This:<br />
<br />
ldx JumpEntry<br />
lda PointerTableH,X<br />
sta Temp+1<br />
lda PointerTableL,X<br />
sta Temp<br />
jmp [Temp]<br />
<br />
; becomes this:<br />
<br />
ldx JumpEntry<br />
lda PointerTableH,X<br />
pha<br />
lda PointerTableL,X<br />
pha<br />
rts<br />
</pre><br />
<br />
Note that PointerTable entries must point to one byte ''before'' the intended target when the RTS trick is used, because RTS will add 1 to the offset.<br />
<br />
If <code>Temp</code> is outside zero page, this saves 6 bytes and 1 cycle. If <code>Temp</code> is within zero page, this saves 4 bytes and costs 1 cycle.<br />
<br />
In either case, it frees up the RAM occupied by <code>Temp</code> for other uses so long as the use of the RTS Trick does not occur at peak stack depth. In addition, it's [[wikipedia:Reentrancy (computing)|reentrant]], which means the NMI and IRQ handlers do not need dedicated 2-byte RAM allocations for their own <code>Temp</code> variables.<br />
<br />
Combining this with the tail call optimization squeezes 1 more byte and 9 more cycles:<br />
<br />
<pre><br />
; This:<br />
<br />
jsr SomeOtherFunction ; MUST NOT modify JumpEntry<br />
ldx JumpEntry<br />
lda PointerTableH,X<br />
pha<br />
lda PointerTableL,X<br />
pha<br />
rts<br />
<br />
; Becomes this:<br />
<br />
ldx JumpEntry<br />
lda PointerTableH,X<br />
pha<br />
lda PointerTableL,X<br />
pha<br />
jmp SomeOtherFunction<br />
</pre><br />
<br />
Here, the CPU runs <code>SomeOtherFunction</code>, then returns to the function from the jump table, then returns to what called this dispatcher. One example is a <code>SomeOtherFunction</code> that mixes player input into the random number generator's entropy pool before calling the routine for a particular game state.<br />
<br />
=== Inline subroutine called only one time through the whole program ===<br />
<br />
There is no reason to call a subroutine if it is only called a single time.<br />
It would be more optimal to just insert the code where the subroutine is called.<br />
However this makes the code less structured and harder to understand.<br />
[[wikipedia:Inline expansion|Inline expansion]] of a subroutine into another subroutine can be done with a macro.<br />
One drawback is that if the subroutine is called in a loop, it may require some JMPing to work around the 128-byte limit on branch length.<br />
<br />
How macros are used depends on the assembler so no code examples will be placed here to avoid further confusion.<br />
In C, the <code>static inline</code> keyword acts as a hint to expand a function as a macro.<br />
<br />
Savings : 4 bytes, 12 cycles.<br />
<br />
=== Easily test 2 upper bits of a variable ===<br />
<br />
<pre><br />
lda FooBar<br />
asl A ;C = b7, N = b6<br />
</pre><br />
<br />
Alternative:<br />
<br />
<pre><br />
bit Foobar ;N = b7, V = b6, regardless of the value of A.<br />
</pre><br />
<br />
This can be e.g. used to poll the sprite-0-hit flag in $2002.<br />
<br />
=== Avoiding the need for CLC/SEC with ADC/SBC ===<br />
<br />
When using ADC #imm, somewhere where it is known carry is already cleared, there's no need to use a CLC instruction. However, that carry is known to be ''set'' (for example, the code is located in a branch that is only ever entered with a BCS instruction), it's still possible to avoid using CLC by just doing ADC #(value-1). The <code>PLOT</code> subroutine in the Apple II Monitor uses this.<br />
<br />
Similarly for SBC #imm: When it is known that carry is ''clear'', SEC instruction can be avoided by just doing SBC #(value-1) or ADC #<-value.<br />
<br />
=== Test bits in decreasing order ===<br />
<br />
<pre><br />
lda foobar <br />
bmi bit7_set <br />
cmp #$40 ; we know that bit 7 wasn't set <br />
bcs bit6_set <br />
cmp #$20 <br />
bcs bit5_set <br />
; and so on<br />
</pre><br />
<br />
Or the value of A doesn't need to be preserved :<br />
<br />
<pre><br />
lda foobar <br />
bmi bit7_set <br />
asl<br />
bmi bit6_set <br />
asl<br />
bmi bit5_set <br />
; and so on<br />
</pre><br />
<br />
This saves one byte per comparison.<br />
<br />
=== Test bits in increasing order ===<br />
<br />
<pre><br />
lda foobar <br />
lsr<br />
bcs bit0_set<br />
lsr<br />
bcs bit1_set<br />
lsr<br />
bcs bit2_set<br />
; and so on<br />
</pre><br />
<br />
Note: This does not preserve the value of A.<br />
<br />
=== Test bits without destroying the accumulator ===<br />
The AND instruction can be used to test bits, but this destroy the value in the accumulator.<br />
The BIT can do this but it has no immediate adressing mode.<br />
A way to do it is to look for an opcode that has the bits that needs to be tested, and using bit $xxxx on this opcode.<br />
<br />
<pre><br />
Example<br />
lda foobar<br />
and #$30<br />
beq bits_clear<br />
lda foobar<br />
....<br />
<br />
bits_clear<br />
lda foobar<br />
.....<br />
</pre><br />
<br />
becomes :<br />
<br />
<pre><br />
Example<br />
lda foobar<br />
bit _bmi_instruction ;equivalent to and #$30 but preserves A<br />
beq bits_clear<br />
....<br />
<br />
bits_clear<br />
.....<br />
<br />
anywhere_in_the_code<br />
....<br />
_bmi_instruction ;The BMI opcode = $30<br />
bmi somewhere<br />
</pre><br />
<br />
Savings : 2 cycles, 3 bytes<br />
<br />
=== Test for equality preserving carry ===<br />
To test whether A equals some other value, EOR can be used instead of CMP to avoid overwriting the carry flag. However, unlike CMP, EOR destroys A.<ref>[https://archive.org/details/eor6502 EOR #$FF - 6502 Ponderables and Befuddlements], puzzle $00</ref><br />
<br />
Before:<br />
<pre><br />
php ; store carry<br />
cmp myVal<br />
beq equal<br />
plp ; restore carry; A != myVal<br />
...<br />
equal:<br />
plp ; restore carry; A == myVal<br />
...<br />
</pre><br />
<br />
After (unlike the previous snippet, destroys A):<br />
<pre><br />
eor myVal<br />
beq equal<br />
... ; A was not equal to myVal<br />
equal:<br />
... ; A was equal to myVal<br />
</pre><br />
<br />
If necessary, the original value of A can be restored with another EOR, which is still faster than the first snippet:<br />
<pre><br />
eor myVal<br />
beq equal<br />
eor myVal ; A was not equal to myVal; restore A<br />
...<br />
equal:<br />
eor myVal ; restore A<br />
...<br />
</pre><br />
<br />
Savings: 7 cycles and 3 bytes if A destroyed, 3 cycles and -1 byte if A preserved.<br />
<br />
=== Test whether all specified bits are set, preserving carry ===<br />
To test whether all specified bits are set, EOR & AND can be used instead of AND & CMP to avoid overwriting the carry flag.<ref>foobles on NESDev Discord 2023-08-30 (UTC)</ref><br />
<br />
Before (testing bits 7, 6, 1 and 0 of A):<br />
<br />
<pre><br />
php ; preserve carry<br />
and #%11000011<br />
cmp #%11000011<br />
beq all_set<br />
plp ; not all set<br />
...<br />
all_set:<br />
plp<br />
...<br />
</pre><br />
<br />
After:<br />
<br />
<pre><br />
eor #$ff<br />
and #%11000011<br />
beq all_set<br />
... ; not all set<br />
all_set:<br />
...<br />
</pre><br />
<br />
Savings: 7 cycles, 3 bytes.<br />
<br />
=== Use opposite rotate instead of a great number of shifts ===<br />
<br />
To retrieve the 3 highest bits of a value in the low positions, it is tempting to do 5 LSRs in a row. However, if it is not needed for the 5 top bits to be cleared, this is more efficient:<br />
<br />
<pre><br />
lda value ; got: 76543210 c<br />
rol ; got: 6543210c 7<br />
rol ; got: 543210c7 6 <br />
rol ; got: 43210c76 5<br />
rol ; got: 3210c765 4<br />
; Only care about these ^^^<br />
</pre><br />
<br />
It works the same for replacing 5 ASLs with 4 RORs.<br />
<br />
3 RORs can replace 6 ASLs :<br />
<br />
<pre><br />
lda value ; got: 76453210 c<br />
ror ; got: c7654321 0<br />
ror ; got: 0c765432 1<br />
ror ; got: 10c76543 2<br />
and #$C0 ; got: 10------<br />
</pre><br />
<br />
=== Avoid compare instructions in loops ===<br />
<br />
In a loop, comparing the loop counter using CMP/CPX/CPY #constant can often be avoided by choosing the direction of the loop and the final value carefully, so the branch instruction can operate using only the Z and N flags from INX/DEX/etc.<br />
<br />
Increasing values of X up to 127, starting from 255 or 0-127:<br />
<pre><br />
loop:<br />
...<br />
inx<br />
bpl loop<br />
</pre><br />
<br />
Increasing values of X up to 255:<br />
<pre><br />
loop:<br />
...<br />
inx<br />
bne loop<br />
</pre><br />
<br />
Decreasing values of X down to 1:<br />
<pre><br />
loop:<br />
...<br />
dex<br />
bne loop<br />
</pre><br />
<br />
Decreasing values of X down to 0, starting from 0-128:<br />
<pre><br />
loop:<br />
...<br />
dex<br />
bpl loop<br />
</pre><br />
<br />
Decreasing values of X down to 128, starting from 129-255 or 0:<br />
<pre><br />
loop:<br />
...<br />
dex<br />
bmi loop<br />
</pre><br />
<br />
Arrays can be offset by a constant to get a suitable final value for the loop counter:<br />
<pre><br />
; copy indexes 10-13 from my_array to $2007<br />
ldx #252 ; 256 - number of bytes<br />
loop:<br />
lda my_array-242,x ; 242 = first X - first index in my_array<br />
sta $2007<br />
inx<br />
bne loop<br />
</pre><br />
<br />
Savings: 2 cycles, 2 bytes (less if applying an offset to an array prevents using zero page addressing).<br />
<br />
== Optimise speed at the expense of size ==<br />
<br />
Those optimisations will make code faster to execute, but use more ROM. Therefore, it is useful in NMI routines and other things that need to run fast.<br />
<br />
=== Use identity look-up table instead of temp variable ===<br />
<br />
''Main article: [[Identity table]]''<br />
<br />
<pre><br />
Example<br />
ldx Foo<br />
lda Bar<br />
stx Temp<br />
clc<br />
adc Temp ;A = Foo + Bar<br />
</pre><br />
<br />
becomes :<br />
<br />
<pre><br />
Example<br />
ldx Foo<br />
lda Bar<br />
clc<br />
adc Identity,X ;A = Foo + Bar<br />
<br />
Identity<br />
.byt $00, $01, $02, $03, .....<br />
</pre><br />
<br />
If the program is very large (such as in large games), it is possible that this way eventually saves ROM; also, it might save one byte of RAM in some circumstances.<br />
<br />
Savings : 2 cycles<br />
<br />
=== Use look-up table to shift left 4 times ===<br />
Provided that the high nibble is already cleared, the value can be shifted left by 4 by making a look-up table.<br />
<br />
<pre><br />
Example:<br />
lda rownum<br />
asl A<br />
asl A<br />
asl A<br />
asl A<br />
rts<br />
</pre><br />
<br />
becomes<br />
<br />
<pre><br />
Example:<br />
ldx rownum<br />
lda times_sixteen,x<br />
rts<br />
<br />
times_sixteen:<br />
.byt $00, $10, $20, $30, $40, $50, $60, $70<br />
.byt $80, $90, $A0, $B0, $C0, $D0, $E0, $F0<br />
</pre><br />
<br />
In very large programs, this might save some ROM space. However, it will use up the X register, so it might not be ideal.<br />
<br />
Savings: 4 cycles<br />
<br />
== Optimise code size at the expense of cycles ==<br />
<br />
Those optimisations will produce code that is smaller but takes more cycles to execute. Therefore, it can be used in the parts of the program that do not have to be fast.<br />
<br />
=== Use the stack instead of a temp variable ===<br />
<br />
<pre><br />
Example<br />
lda Foo<br />
sta Temp<br />
lda Bar<br />
....<br />
....<br />
lda Temp ;Restores Foo<br />
.....<br />
</pre><br />
<br />
becomes:<br />
<br />
<pre><br />
Example<br />
lda Foo<br />
pha<br />
lda Bar<br />
....<br />
....<br />
pla ;Restores Foo<br />
.....<br />
</pre><br />
<br />
Savings : 2 bytes.<br />
<br />
=== Use an "intelligent" argument system ===<br />
<br />
Each time a routine needs multiple bytes of arguments (>3) it's hard to code it without wasting a lot of bytes.<br />
<br />
<pre><br />
Example<br />
lda Argument1<br />
sta Temp<br />
lda Argument2<br />
ldx Argument3<br />
ldy Argument4<br />
jsr RoutineWhichNeeds4Args<br />
.....<br />
</pre><br />
<br />
Becomes something like:<br />
<br />
<pre><br />
Example<br />
jsr PassArguments<br />
.dw RoutineWhichNeeds4Args<br />
.db Argument1, Argument2, Argument3, Argument4<br />
.db $00<br />
....<br />
<br />
PassArguments<br />
pla <br />
tay <br />
pla <br />
pha ; put the high byte back <br />
sta pointer+1 <br />
ldx #$00 <br />
beq SKIP <br />
LOOP <br />
sta parameters,x <br />
inx <br />
SKIP <br />
iny ; pointing one short first pass here fixes that <br />
lda (pointer),y <br />
bne LOOP <br />
iny <br />
lda (pointer),y <br />
beq LOOP<br />
<br />
dey ; fix the return address guess we can't return to a <br />
; break <br />
tya <br />
pha <br />
jmp (parameters)<br />
</pre><br />
<br />
Syscalls in Apple ProDOS<ref>''ProDOS 8 Technical Reference Manual''</ref> and FDS BIOS work this way.<br />
<br />
Savings : Complicated to estimate - only saves bytes if the trick is used fairly often across the program, in order to compensate for the size of the PassArguments routine.<br />
<br />
=== Using relative branch instruction instead of absolute ===<br />
<br />
If the state of one of the processor flags is already known at this point and the branch target is not too far away, then a condition branch instruction can be used. For example,<br />
<br />
lda #1<br />
jmp target<br />
<br />
becomes<br />
<br />
lda #1<br />
bne target ; zero flag is always clear<br />
<br />
or<br />
<br />
lda #1<br />
bpl target ; negative flag is always clear<br />
<br />
Savings : 1 byte.<br />
<br />
=== BIT trick ===<br />
<br />
The BIT instruction ($24 and $2C) can be used to "mask out" the following 1- or 2-byte instruction without affecting non-flags CPU registers. Care should be taken, however, to ensure a masked 2-byte instruction does not match the address of a register with read side effects, as this would trigger them.<br />
<br />
This trick can be used to create multiple entry points to a subroutine that takes one argument in a register. For example,<br />
<br />
sub_11:<br />
lda #11<br />
sub:<br />
sta $2007<br />
sta $2007<br />
rts<br />
...<br />
lda #5<br />
jsr sub<br />
lda #7<br />
jsr sub<br />
jsr sub_11<br />
lda #13<br />
jsr sub<br />
<br />
becomes<br />
<br />
sub_5:<br />
lda #5<br />
.byte $2c ; BIT absolute opcode<br />
sub_7:<br />
lda #7 ; turns into the operand of BIT if sub_5 was called<br />
.byte $2c ; BIT absolute opcode<br />
sub_11:<br />
lda #11 ; turns into the operand of BIT if sub_5 or sub_7 was called<br />
sub:<br />
sta $2007<br />
sta $2007<br />
rts<br />
...<br />
jsr sub_5<br />
jsr sub_7<br />
jsr sub_11<br />
lda #13<br />
jsr sub<br />
<br />
Code size is reduced if <tt>sub_5</tt> and <tt>sub_7</tt> are called more than once.<br />
<br />
<ref>Used in ''Super Mario Bros.'' (e.g. <tt>MoveSpritesOffscreen</tt> in doppelganger's disassembly)</ref><br />
<br />
== See also ==<br />
*[[Synthetic instructions]]<br />
<br />
== Notes ==<br />
<references /></div>Fiskbithttps://www.nesdev.org/w/index.php?title=CPU_memory_map&diff=21669CPU memory map2024-03-18T10:25:18Z<p>Fiskbit: Fixes two references to the now-removed "cartridge space". Clarifies that the vectors in the unmapped space are supplied by the cartridge.</p>
<hr />
<div>{| class="tabular"<br />
! Address range || Size || Device<br />
|-<br />
| $0000–$07FF || $0800 || 2 KB internal RAM<br />
|-<br />
| $0800–$0FFF || $0800 ||rowspan=3| [[Mirroring#Memory Mirroring|Mirrors]] of $0000–$07FF<br />
|-<br />
| $1000–$17FF || $0800<br />
|-<br />
| $1800–$1FFF || $0800<br />
|-<br />
| $2000–$2007 || $0008 || [[PPU registers|NES PPU registers]]<br />
|-<br />
| $2008–$3FFF || $1FF8 || Mirrors of $2000–$2007 (repeats every 8 bytes)<br />
|-<br />
| $4000–$4017 || $0018 || [[APU|NES APU]] and [[2A03|I/O registers]]<br />
|-<br />
| $4018–$401F || $0008 || APU and I/O functionality that is normally disabled. See [[CPU Test Mode]].<br />
|-<br />
| $4020–$FFFF<br/>''• $6000–$7FFF<br/>• $8000–$FFFF'' || $BFE0<br/>''$2000<br/>$8000'' || Unmapped. Available for cartridge use.<br/>''Usually cartridge RAM, when present.<br/>Usually cartridge ROM and [[mapper]] registers.''<br />
|}<br />
<br />
* Some parts of the 2 KiB of internal RAM at $0000–$07FF have predefined purposes dictated by the 6502 architecture:<br />
** $0000-$00FF: The zero page, which can be accessed with fewer bytes and cycles than other addresses<br />
** $0100–$01FF: The page containing the stack, which can be located anywhere here, but typically starts at $01FF<br />
: Games may divide up the rest however the programmer deems useful. See [[Sample RAM map]] for an example allocation strategy for this RAM. Most commonly, $0200-$02FF is used for the OAM buffer to be copied to PPU OAM during vblank.<br />
<br />
* The unmapped space at $4020-$FFFF can be used by cartridges for any purpose, such as ROM, RAM, and registers. Many common mappers place ROM and save/work RAM in these locations:<br />
** $6000–$7FFF: Battery-backed save or work RAM (usually referred to as WRAM or PRG-RAM)<br />
** $8000–$FFFF: ROM and mapper registers (see [[MMC1]] and [[UxROM]] for examples)<br />
: The cartridge is able to passively observe reads from and writes to any address in the CPU address space, even outside this unmapped space, except for reads from $4015, the only readable register that is internal to the CPU. The cartridge can map writable registers anywhere, but its readable memory can only be placed where it does not interfere with other readable hardware, which would produce a [[bus conflict]]. While cartridges can map readable memory at $4000-$4014 and $4018-$401F, a quirk in the 2A03's register decoding can cause DMA to misbehave if the CPU is halted while reading from $4000-$401F, so it is recommended that cartridges only map readable memory from $4020-$FFFF.<br />
<br />
* If using [[APU DMC|DPCM playback]], samples are limited to the following practical range:<br />
** $C000–$FFF1: DPCM sample data<br />
: Sample playback wraps around from $FFFF to $8000. The highest sample starting address is $FFC0 and longest sample is $FF1 bytes, so the full DPCM range is $C000-$FFFF and $8000-$8FB0, but making use of the wraparound is challenging because of banking and the presence of the CPU vectors.<br />
<br />
* The CPU expects interrupt vectors in a fixed place at the end of the unmapped space:<br />
** $FFFA–$FFFB: NMI vector, which points at an [[NMI]] handler<br />
** $FFFC–$FFFD: Reset vector, which points at [[init code|code to initialize the NES chipset]]<br />
** $FFFE–$FFFF: IRQ/BRK vector, which may point at a mapper's [[IRQ|interrupt]] handler (or, less often, a handler for APU interrupts)<br />
: These vectors are supplied by the cartridge. If a mapper doesn't fix $FFFA–$FFFF to some known bank (normally by fixing an entire bank-sized region at the top of the address space, such as $C000-$FFFF, to a specific bank) nor use some sort of reset detection, the vectors need to be stored in all banks.<br />
<br />
* Reading from memory that is not mapped to anything normally returns [[Open bus behavior|open bus]]. The cartridge hardware may affect open bus behavior across the entire CPU address space, such as by pulling bits high or low.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=CPU_memory_map&diff=21668CPU memory map2024-03-18T09:18:57Z<p>Fiskbit: Clarifies that the "cartridge space" is really unmapped space cartridges can use. Adds the extremely common cartridge RAM and ROM mapping to the table to avoid users thinking ROM starts at $4020.</p>
<hr />
<div>{| class="tabular"<br />
! Address range || Size || Device<br />
|-<br />
| $0000–$07FF || $0800 || 2 KB internal RAM<br />
|-<br />
| $0800–$0FFF || $0800 ||rowspan=3| [[Mirroring#Memory Mirroring|Mirrors]] of $0000–$07FF<br />
|-<br />
| $1000–$17FF || $0800<br />
|-<br />
| $1800–$1FFF || $0800<br />
|-<br />
| $2000–$2007 || $0008 || [[PPU registers|NES PPU registers]]<br />
|-<br />
| $2008–$3FFF || $1FF8 || Mirrors of $2000–$2007 (repeats every 8 bytes)<br />
|-<br />
| $4000–$4017 || $0018 || [[APU|NES APU]] and [[2A03|I/O registers]]<br />
|-<br />
| $4018–$401F || $0008 || APU and I/O functionality that is normally disabled. See [[CPU Test Mode]].<br />
|-<br />
| $4020–$FFFF<br/>''• $6000–$7FFF<br/>• $8000–$FFFF'' || $BFE0<br/>''$2000<br/>$8000'' || Unmapped. Available for cartridge use.<br/>''Usually cartridge RAM, when present.<br/>Usually cartridge ROM and [[mapper]] registers.''<br />
|}<br />
<br />
* Some parts of the 2 KiB of internal RAM at $0000–$07FF have predefined purposes dictated by the 6502 architecture:<br />
** $0000-$00FF: The zero page, which can be accessed with fewer bytes and cycles than other addresses<br />
** $0100–$01FF: The page containing the stack, which can be located anywhere here, but typically starts at $01FF<br />
: Games may divide up the rest however the programmer deems useful. See [[Sample RAM map]] for an example allocation strategy for this RAM. Most commonly, $0200-$02FF is used for the OAM buffer to be copied to PPU OAM during vblank.<br />
<br />
* The unmapped space at $4020-$FFFF can be used by cartridges for any purpose, such as ROM, RAM, and registers. Many common mappers place ROM and save/work RAM in these locations:<br />
** $6000–$7FFF: Battery-backed save or work RAM (usually referred to as WRAM or PRG-RAM)<br />
** $8000–$FFFF: ROM and mapper registers (see [[MMC1]] and [[UxROM]] for examples)<br />
: The cartridge is able to passively observe reads from and writes to any address in the CPU address space, even outside this cartridge space, except for reads from $4015, the only readable register that is internal to the CPU. The cartridge can map writable registers anywhere, but its readable memory can only be placed where it does not interfere with other readable hardware, which would produce a [[bus conflict]]. While cartridges can map readable memory at $4000-$4014 and $4018-$401F, a quirk in the 2A03's register decoding can cause DMA to misbehave if the CPU is halted while reading from $4000-$401F, so it is recommended that cartridges only map readable memory from $4020-$FFFF.<br />
<br />
* If using [[APU DMC|DPCM playback]], samples are limited to the following practical range:<br />
** $C000–$FFF1: DPCM sample data<br />
: Sample playback wraps around from $FFFF to $8000. The highest sample starting address is $FFC0 and longest sample is $FF1 bytes, so the full DPCM range is $C000-$FFFF and $8000-$8FB0, but making use of the wraparound is challenging because of banking and the presence of the CPU vectors.<br />
<br />
* The CPU expects interrupt vectors in a fixed place at the end of the cartridge space:<br />
** $FFFA–$FFFB: NMI vector, which points at an [[NMI]] handler<br />
** $FFFC–$FFFD: Reset vector, which points at [[init code|code to initialize the NES chipset]]<br />
** $FFFE–$FFFF: IRQ/BRK vector, which may point at a mapper's [[IRQ|interrupt]] handler (or, less often, a handler for APU interrupts)<br />
: If a mapper doesn't fix $FFFA–$FFFF to some known bank (normally by fixing an entire bank-sized region at the top of the address space, such as $C000-$FFFF, to a specific bank) nor use some sort of reset detection, the vectors need to be stored in all banks.<br />
<br />
* Reading from memory that is not mapped to anything normally returns [[Open bus behavior|open bus]]. The cartridge hardware may affect open bus behavior across the entire CPU address space, such as by pulling bits high or low.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=DMA&diff=21667DMA2024-03-17T01:26:29Z<p>Fiskbit: /* Register conflicts */ Adds Twin Famicom and Famicom Titler to the list of consoles known to clock joypads per CPU cycle.</p>
<hr />
<div>The 2A03 contains a pair of DMA units, one for copying sprite data to PPU [[OAM]] and the other for copying DPCM sample data to the APU's [[APU DMC|DMC]] sample buffer. DMA is required for DPCM playback, and it is difficult to fill OAM without DMA. Unfortunately, DMC DMA can also result in data loss when reading registers with side effects, such as the joypads.<br />
<br />
==Summary==<br />
* The CPU alternates between cycles on which DMA can get (read) and cycles on which DMA can put (write). These are the first and second halves of APU cycles, respectively. At power-on, whether the first CPU cycle is get or put is random.<br />
* If DMA tries to get on a put cycle, it waits and tries again next cycle. This wait is called an alignment cycle.<br />
* DMA can only halt on CPU read cycles. On write cycles, the halt fails and the DMA unit tries again next CPU cycle, repeating until successful.<br />
* OAM DMA halts the CPU, performs an optional alignment cycle, and then gets and puts 256 times, taking 513 or 514 cycles. It attempts to halt on the first CPU cycle after the $4014 write.<br />
* DMC DMA halts the CPU, performs a dummy cycle and an optional alignment cycle, and then gets once, taking 3 or 4 cycles. <br />
* The first, "load" DMC DMA after the $4015 write attempts to halt on the get cycle during the 2nd following APU cycle. The other, "reload" DMC DMAs attempt to halt on a put cycle. Failed halts try again on the next CPU cycle, repeating until successful.<br />
* The DMC DMA get takes precedence over OAM DMA get, delaying it, but the DMA cycles otherwise overlap, reducing the total cycle cost. This delay can force OAM DMA to add an alignment cycle.<br />
* DMC DMA has [[#Bugs|bugs triggered by stopping the sample at specific times]].<br />
* DMC DMA can [[#Register conflicts|corrupt joypad and PPUDATA ($2007) reads and cause extraneous reads of $4015-4017]].<br />
<br />
==Cadence==<br />
The DMA units cannot just read or write on any cycle as they wish. Instead, they alternate between '''get''' cycles where they can read and '''put''' cycles where they can write. If they need to perform an action that is not permitted on the current cycle, they wait.<br />
<br />
Get and put cycles are aligned to the first and second halves of the APU clock, respectively (called apu_clk1 and apu_clk2 in Visual2A03). While these cycles are sometimes described as even and odd CPU cycles, this is not accurate because the CPU and APU randomly power into either of 2 alignments relative to each other. Therefore, get and put may occur on different CPU cycle parities across different power cycles.<br />
<br />
==Behavior==<br />
During the DMA process, the CPU is halted and the 2A03's address and data lines are used for data transfer. The process involves a combination of no-operation cycles and access cycles. No-operation cycles come in 3 equivalent types: the halt cycle, a DMC-only dummy cycle, and an optional alignment cycle.<br />
<br />
When DMA is scheduled, the associated DMA unit attempts to halt the CPU. The CPU only allows this on read cycles. If the CPU is writing, it ignores the halt and the DMA unit waits until the next cycle to try again, repeating until successful. Delays of up to 3 cycles are possible, with read-modify-write instructions having 2 consecutive writes and interrupts having 3. The halting process itself takes 1 CPU cycle, during which no useful work is done.<br />
<br />
Once the CPU is halted, the DMA unit may need to perform some amount of non-access setup, taking up to 2 cycles. The exact timing of when DMA is scheduled and what kind of setup it needs depends on the type of DMA.<br />
<br />
The CPU is halted using its internal RDY input. When RDY is deasserted, the 6502 core repeats the last read cycle indefinitely, making no forward progress nor handling interrupts. On 2A03 CPUs, these repeated reads are externally visible on any no-operation DMA cycle, causing data loss if reading a register with side effects. On 2A07 CPUs, it is suspected that a different address (perhaps the DMA address) is on the bus, instead, during all no-operation cycles. See [[#Register conflicts|Register conflicts]] for more information.<br />
<br />
When the DMA process completes, the CPU performs the read it attempted when halted.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - General behavior</div><br />
<div class="mw-collapsible-content"><br />
* DMA halts normally:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA halt is delayed by writes:<br />
CPU writes <- DMA attempts to halt<br />
CPU writes <- DMA attempts to halt<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA has a non-access cycle:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) CPU reads from address A <- DMA does not read or write<br />
(halted) DMA accesses address B<br />
CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===OAM DMA===<br />
-----<br />
OAM DMA copies 256 bytes from a CPU page to PPU OAM via the [[PPU_registers#OAMDATA|OAMDATA ($2004)]] register. It is triggered by writing the page number (the high byte of the address) to [[PPU_registers#OAMDMA|OAMDMA ($4014)]]. OAM DMA is scheduled to halt the CPU on the first cycle after the register write. In the common case, it performs a halt cycle, an optional alignment cycle, and 256 get/put pairs. <br />
<br />
The 256 get/put pairs copy forward from the start of the page. Because DMA can only read on get cycles, an alignment cycle performing no useful work may be required before being able to read. All together, OAM DMA on its own takes 513 or 514 cycles, depending on whether alignment is needed.<br />
<br />
OAM DMA will copy from the page most recently written to $4014. This means that read-modify-write instructions such as INC $4014, which are able to perform a second write before the CPU can be halted, will copy from the second page written, not the first.<br />
<br />
OAM DMA has a lower priority than DMC DMA. If a DMC DMA get occurs during OAM DMA, OAM DMA is briefly paused. (See [[#DMC DMA during OAM DMA|DMC DMA during OAM DMA]])<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* Alignment is not needed:<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Alignment is needed:<br />
(put) CPU writes to $4014<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===DMC DMA===<br />
-----<br />
DMC DMA copies a single byte to the DMC unit's sample buffer. This occurs automatically after the DMC enable bit, bit 4, of the [[APU#Status_($4015)|sound channel enable register ($4015)]] is set to 1, which starts DPCM sample playback using the current DMC settings in [[APU_DMC#Overview|registers $4010-4013]]. DMC DMA is scheduled when all of DPCM playback is enabled, there are bytes left in the sample, and the sample buffer is empty (see [[APU_DMC#Memory_reader|Memory reader]] and [[APU_DMC#Output_unit|Output unit]]). In the common cases, DMC DMA performs a halt cycle, a dummy cycle, an optional alignment cycle, and a get.<br />
<br />
The exact timing depends on the type of DMC DMA. There are two types: load and reload. Load DMAs occur after $4015 D4 is set, but only if the sample buffer is empty. They are scheduled to halt the CPU on a get cycle during the 2nd APU cycle after the write (that is, the 3rd or 4th CPU cycle). Reload DMAs occur in response to the sample buffer being emptied. Unlike load DMAs, they are scheduled to halt the CPU on a put cycle.<br />
<br />
After the halt, DMC DMA always performs a dummy cycle where no work is done. If the next cycle is not a get cycle, then a cycle will be spent on alignment. Then the DMA read is performed.<br />
<br />
DMC DMA normally takes 3 or 4 cycles, depending on whether alignment is needed. Because load and reload DMAs schedule on different cycle types, load DMAs take 3 cycles and reload DMAs take 4 unless the halt is delayed by an odd number of cycles. However, bugs can cause additional cycles; see [[#Bugs|Bugs]] below.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA</div><br />
<div class="mw-collapsible-content"><br />
* Load DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Load DMA (delayed 1 cycle):<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA:<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 1 cycle):<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 2 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 3 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
====Bugs====<br />
DMC DMA suffers from two bugs<ref>[https://forums.nesdev.org/viewtopic.php?p=250170#p250170 Forum post:] Fiskbit's manual DMA test suite</ref><ref>[https://forums.nesdev.org/viewtopic.php?p=275734#p275734 Forum post:] Fiskbit's explicit and implicit stop tests</ref> related to sample playback stopping around the time [[APU_DMC#Output_unit|a DMC output cycle ends]], which is what empties the sample buffer and triggers a reload DMA. This can happen explicitly, where the sample is stopped by clearing $4015 D4, or implicitly, where a non-looping 1-byte sample is started while the sample buffer is empty shortly before a reload DMA would schedule. Implicit stops require this type of sample because the load DMA for the first byte when the sample buffer is empty is the only way to implicitly end the sample just before a reload DMA; longer samples will instead be ended by the reload DMA itself, as normal.<br />
<br />
When sample playback is stopped during the APU cycle before a reload DMA would schedule (that is, on the 2nd or 3rd CPU cycle before the halt attempt), the DMA starts, but is aborted after a single cycle. If the halt is delayed due to a write cycle, the aborted DMA doesn't occur at all. This aborted DMA schedules regardless of how playback was stopped, whether explicitly or implicitly. In the implicit case, the write to begin the sample will normally be the 4th APU cycle before the reload DMA would schedule (8th or 9th CPU cycle before).<br />
<br />
On RP2A03H and late RP2A03G CPUs, when playback is stopped implicitly on the same APU cycle that a reload DMA would schedule (that is, the 1st CPU cycle before the halt attempt), an unexpected reload DMA occurs from the same address. This extra byte goes into the sample buffer and is played after the first byte, as with any normal fetch. On RP2A03G CPUs, this bug was introduced sometime in 1990; earlier chips are unaffected.<br />
<br />
It is not known whether 2A07 CPUs are affected by these bugs. Some clone hardware is known to be affected, and behavior on affected clones may differ from official CPUs. For example, UA6527P-based clones feature both the aborted DMA and unexpected DMA bugs, but samples take 1 APU cycle longer to end than on official CPUs, so to trigger these bugs with implicit stops, the sample-ending byte must be fetched 1 APU cycle earlier.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA bugs</div><br />
<div class="mw-collapsible-content"><br />
* Explicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC disabled<br />
(put) / during this APU cycle <- DMC disabled<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Implicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address C <- DMA halt cycle<br />
(get) CPU reads from address C <- CPU resumes execution<br />
<br />
* Implicit-stop unexpected DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
The implicit-stop aborted DMA can be prevented with carefully placed write cycles. This can be necessary for synchronized code, where the aborted DMA's odd number of cycles can invert cycle parity. The following code synchronizes to a put cycle and uses precise write cycles to prevent any aborted DMA that may occur:<br />
STx $4015 ; Initiate DMC DMA.<br />
STx zp ; Force load DMA to the 4th cycle.<br />
; (If on a UA6527P-based clone, place a NOP here.)<br />
STx zp ; Override the aborted DMA.<br />
; The first cycle of the next instruction is a put cycle.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - aborted DMA workaround</div><br />
<div class="mw-collapsible-content"><br />
* Implicit-stop aborted DMA bypass (write on get):<br />
(get) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) CPU reads<br />
(get) CPU reads<br />
(put) CPU writes<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
<br />
* Implicit-stop aborted DMA bypass (write on put):<br />
(put) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
</div></div></div><br />
<br />
===DMC DMA during OAM DMA===<br />
DMC and OAM use independent DMA units that only interact when both attempt to access memory on the same cycle. When accesses collide, DMC DMA is allowed to run and OAM DMA is paused, trying again on the next cycle. This can cause OAM DMA to have to perform an additional alignment cycle before continuing. No-operation cycles are allowed to overlap with each other and with access cycles, allowing cycles to be saved.<br />
<br />
In the common case, DMC DMA occurring during OAM DMA will cost only 2 cycles: 1 cycle for the DMC DMA get and then 1 cycle for OAM DMA to align back to a get. However, if DMC DMA occurs at the end of OAM DMA, it can take 1 or 3 cycles. If it schedules for the second-to-last put, its get will occur on the first cycle after OAM DMA, taking just 1 cycle total. If it schedules for the last put, it will instead extend 3 cycles beyond the end of OAM DMA.<br />
<br />
OAM DMA is sometimes used to synchronize code to avoid conflicts with DMC DMA when reading hardware registers, but because DMC DMA takes an odd number of cycles if it lands at the end, synchronization is not guaranteed.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA during OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA at the start of OAM DMA (write on get), taking 2 cycles<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xx00 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
<br />
* DMC DMA at the start of OAM DMA (write on put), taking 2 cycles<br />
(put) CPU writes to $4014 <- DMC DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA dummy cycle, OAM DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from $xx00<br />
(halted) (put) OAM DMA writes to $2004<br />
...<br />
<br />
* DMC DMA in the middle of OAM DMA, taking 2 cycles<br />
...<br />
(halted) (get) OAM DMA reads from address C<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from address C+1 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from address C+2<br />
...<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 1 cycle<br />
...<br />
(halted) (get) OAM DMA reads from $xxFE<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xxFF <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 3 cycles<br />
...<br />
(halted) (get) OAM DMA reads from $xxFF<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMC DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
==Register conflicts==<br />
On the 2A03, while the CPU is halted, it repeats the read cycle on which it was halted during every no-operation DMA cycle (that is, when the DMA units are not reading or writing). If the CPU was reading a register with side-effects, this can cause data to be lost. While this isn't realistically a problem with OAM DMA because of its particular timing constraints, it is a very real problem with DMC DMA that must usually be worked around. Example registers include PPUSTATUS ($2002), PPUDATA ($2007), and sound status ($4015). When conflicting with DMC DMA, these will see 2 or more extra reads. (Note that $2007 reads on adjacent cycles may have unexpected behavior.)<br />
<br />
Most frequently, these DMC DMA conflicts occur with joypad reads, though the mechanism is slightly different. Joypads are clocked via direct lines from the CPU, called joypad 1 /OE and joypad 2 /OE, rather than going over the address bus. These output enables remain asserted the entire CPU cycle and even across adjacent cycles if they're both reading the same joypad register. Therefore, controllers only see a single read for each contiguous set of reads of a joypad register.<br />
<br />
The console type affects joypad extra-read behavior. On the RF Famicom, additional hardware outside the 2A03 only passes joypad 1 /OE and joypad 2 /OE through during one half of the clock cycle, meaning the joypad sees a clock on every single CPU read cycle rather than just every contiguous set<ref>[https://forums.nesdev.org/viewtopic.php?p=275946#p275946 Forum post:] lidnariq's RF Famicom joypad clocking explanation</ref>. The RF Famicom, Twin Famicom, and Famicom Titler are known to behave this way. The AV Famicom and NES-001 are confirmed to use the per-contiguous-set behavior.<ref>[https://forums.nesdev.org/viewtopic.php?p=275468#p275468 Forum post:] Fiskbit's joypad read cycle breakdown</ref><br />
<br />
This is further complicated by esoteric behavior regarding how 2A03 registers are activated: instead of checking the full 2A03 address bus, it checks bits 4-0 from the 2A03 address bus and bits 15-5 from the 6502 core. The 6502 core keeps the same address while halted, so if it was reading from $4000-401F, the DMA address can unintentionally activate 2A03 registers. This can lead to bus conflicts and an extra read from the other joypad, and can even prevent an extra read of the current joypad.<ref>[https://forums.nesdev.org/viewtopic.php?p=275132#p275132 Forum post:] Fiskbit's APU register activation test</ref><br />
<br />
The 2A07 fixes these extra read problems, but the mechanism is not yet understood. Experimentally, the CPU still performs a read on the halting cycle; if OAM DMA is done from the $4000 page, the open bus value used by the OAM DMA is the opcode of the instruction following the $4014 write. This means that 6502 core reads still occur when halted, at least on the first cycle. Like on NTSC, this DMA also does not trigger 2A07 registers if the 6502 core is not reading from $4000-401F. Unlike NTSC, reading a joypad register when DMA reads an address that matches the other joypad register in its low 5 bits does not clock the other joypad.<br />
<br />
Workarounds exist for this issue. Most commonly, [[Controller_reading_code#DPCM_Safety_using_Repeated_Reads|joypads are read multiple times]] until the same result is seen twice in row, reducing or eliminating the chance of accepting corrupted data. However, any collisions during this time may corrupt the DPCM data, and this strategy is not suitable for all affected registers. Alternatively, [[Controller_reading_code#DPCM_Safety_using_OAM_DMA|reads synchronized using OAM DMA]] can ensure a collision never happens, but this enforces strict timing constraints on the code and has numerous caveats, particularly for functions longer than one DMC output cycle (sample byte period).<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - Register conflicts</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA collides with $2007 read (3 extra reads)<br />
(halted) (put) CPU reads from $2007 <- DMA halt cycle<br />
(halted) (get) CPU reads from $2007 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $2007 <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from $2007 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 ($4016) read (1 or 3 extra reads)<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C000<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (0 or 4 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4016.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C016 and $4016<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (1 extra read of JOYPAD2, 1 or 3 extra of JOYPAD1)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4017.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C017 and $4017<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
*DMC DMA collides with JOYPAD1 read (1 or 3 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4015.<br />
** This causes the 2A03 to read $4015 and ignore the DMA value on the external data bus.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C015, 2A03 reads from $4015 internally<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
</div></div></div><br />
<br />
==References==<br />
:* [https://github.com/emu-russia/breaks/blob/master/BreakingNESWiki_DeepL/APU/dma.md BreakingNESWiki:] DMA circuit analysis<br />
:* [https://forums.nesdev.org/viewtopic.php?t=14120 Forum post:] Disch's OAM/DMC DMA test results<br />
:* [https://forums.nesdev.org/viewtopic.php?p=62690#p62690 Forum post:] Blargg's DMA tests<br />
:* [https://forums.nesdev.org/viewtopic.php?p=231604#p231604 Forum post:] Fiskbit's aligned controller read tests<br />
:* [https://forums.nesdev.org/viewtopic.php?p=95703#95703 Forum post:] cpow's Visual 2A03 DMC vs OAM DMA analysis<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=APU_DMC&diff=21666APU DMC2024-03-15T15:59:16Z<p>Fiskbit: Removes the list of DMC DMA cycle length cases; a similar list now lives in 'Controller reading code' where it's more comprehensive for the task at hand. While this list is convenient, it can be misleading and is not enough to implement DMA correctly.</p>
<hr />
<div>[[Category:APU]]<br />
<br />
The [[APU|NES APU's]] delta modulation channel (DMC) can output 1-bit [[wikipedia:Delta modulation|delta-encoded samples]] or can have its 7-bit counter directly loaded, allowing flexible manual sample playback.<br />
<br />
== Overview ==<br />
<br />
The DMC channel contains the following: memory reader, interrupt flag, sample buffer, [[APU Misc|timer]], output unit, 7-bit output level with up and down counter.<br />
<br />
<pre><br />
Timer<br />
|<br />
v<br />
Reader ---> Buffer ---> Shifter ---> Output level ---> (to the mixer)<br />
</pre><br />
<br />
{| class="wikitable"<br />
| '''$4010''' || <tt>IL--.RRRR</tt> || '''Flags and Rate''' (write)<br />
|-<br />
| bit 7 || <tt>I---.----</tt> || IRQ enabled flag. If clear, the interrupt flag is cleared.<br />
|-<br />
| bit 6 || <tt>-L--.----</tt> || Loop flag<br />
|-<br />
| bits 3-0 || <tt>----.RRRR</tt> || Rate index<br><br />
<!-- If you modify this table, keep the values comma-separated so they can be used without changes in a program --><br />
<pre><br />
Rate $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $A $B $C $D $E $F<br />
------------------------------------------------------------------------------<br />
NTSC 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54<br />
PAL 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50<br />
</pre><br />
<br />
The rate determines for how many CPU cycles happen between changes in the output level during automatic delta-encoded sample playback. For example, on NTSC (1.789773 MHz), a rate of 428 gives a frequency of 1789773/428 Hz = 4181.71 Hz. These periods are all even numbers because there are 2 CPU cycles in an APU cycle. A rate of 428 means the output level changes every 214 APU cycles.<br />
|-<br />
|colspan=3| &nbsp;<br />
|-<br />
| '''$4011''' || <tt>-DDD.DDDD</tt> || '''Direct load''' (write)<br />
|-<br />
| bits 6-0 || <tt>-DDD.DDDD</tt> || The DMC output level is set to D, an unsigned value. If the timer is outputting a clock at the same time, the output level is occasionally not changed properly.[http://forums.nesdev.org/viewtopic.php?p=104491#p104491]<br />
|-<br />
|colspan=3| &nbsp;<br />
|-<br />
| '''$4012''' || <tt>AAAA.AAAA</tt> || '''Sample address''' (write)<br />
|-<br />
| bits 7-0 || <tt>AAAA.AAAA</tt> || Sample address = <tt>%11AAAAAA.AA000000</tt> = <tt>$C000 + (A * 64)</tt><br />
|-<br />
|colspan=3| &nbsp;<br />
|-<br />
| '''$4013''' || <tt>LLLL.LLLL</tt> || '''Sample length''' (write)<br />
|-<br />
| style="white-space: nowrap;" | bits 7-0 || <tt>LLLL.LLLL</tt> || Sample length = <tt>%LLLL.LLLL0001</tt> = <tt>(L * 16) + 1 bytes</tt><br />
|}<br />
<br />
The output level is sent to the [[APU Mixer|mixer]] whether the channel is enabled or not. It is loaded with 0 on power-up, and can be updated by $4011 writes and delta-encoded sample playback.<br />
<br />
Automatic 1-bit [[wikipedia:Delta modulation|delta-encoded sample]] playback is carried out by a combination of three units. The ''memory reader'' fills the 8-bit ''sample buffer'' whenever it is emptied by the sample ''output unit''. The [[APU Status|status register]] is used to start and stop automatic sample playback.<br />
<br />
The '''sample buffer''' either holds a single 8-bit sample byte or is empty. It is filled by the reader and can only be emptied by the output unit; once loaded with a sample byte it will be played back.<br />
<br />
=== Pitch table ===<br />
<br />
{| class="wikitable"<br />
|-<br />
|<br />
| colspan="3" bgcolor = FFDDDD | NTSC<br />
| colspan="3" bgcolor = DDDDFF | PAL<br />
|-<br />
! $4010 || Period || Frequency || Note || Period || Frequency || Note<br />
|-<br />
| $0 <br />
| bgcolor=FFDDDD | $1AC || 4181.71 Hz || C-8 -1.78c<br />
| bgcolor=DDDDFF | $18E || 4177.40 Hz || C-8 -3.56c<br />
|-<br />
| $1<br />
| bgcolor=FFDDDD | $17C || 4709.93 Hz || D-8 +4.16c<br />
| bgcolor=DDDDFF | $162 || 4696.63 Hz || D-8 -.739c<br />
|-<br />
| $2<br />
| bgcolor=FFDDDD | $154 || 5264.04 Hz || E-8 -3.29c<br />
| bgcolor=DDDDFF | $13C || 5261.41 Hz || E-8 -4.15c<br />
|-<br />
| $3<br />
| bgcolor=FFDDDD | $140 || 5593.04 Hz || F-8 +1.67c<br />
| bgcolor=DDDDFF | $12A || 5579.22 Hz || F-8 -2.61c<br />
|-<br />
| $4<br />
| bgcolor=FFDDDD | $11E || 6257.95 Hz || G-8 -3.86c<br />
| bgcolor=DDDDFF | $114 || 6023.94 Hz || G-8 -69.8c<br />
|-<br />
| $5<br />
| bgcolor=FFDDDD | $0FE || 7046.35 Hz || A-8 +1.56c<br />
| bgcolor=DDDDFF | $0EC || 7044.94 Hz || A-8 +1.22c<br />
|-<br />
| $6<br />
| bgcolor=FFDDDD | $0E2 || 7919.35 Hz || B-8 +3.77c<br />
| bgcolor=DDDDFF | $0D2 || 7917.18 Hz || B-8 +3.29c<br />
|-<br />
| $7<br />
| bgcolor=FFDDDD | $0D6 || 8363.42 Hz || C-9 -1.78c<br />
| bgcolor=DDDDFF | $0C6 || 8397.01 Hz || C-9 +5.16c<br />
|-<br />
| $8<br />
| bgcolor=FFDDDD | $0BE || 9419.86 Hz || D-9 +4.16c<br />
| bgcolor=DDDDFF | $0B0 || 9446.63 Hz || D-9 +9.07c<br />
|-<br />
| $9<br />
| bgcolor=FFDDDD | $0A0 || 11186.1 Hz || F-9 +1.67c<br />
| bgcolor=DDDDFF | $094 || 11233.8 Hz || F-9 +9.04c<br />
|-<br />
| $A<br />
| bgcolor=FFDDDD | $08E || 12604.0 Hz || G-9 +8.29c<br />
| bgcolor=DDDDFF | $084 || 12595.5 Hz || G-9 +7.11c<br />
|-<br />
| $B<br />
| bgcolor=FFDDDD | $080 || 13982.6 Hz || A-9 -12.0c<br />
| bgcolor=DDDDFF | $076 || 14089.9 Hz || A-9 +1.22c<br />
|-<br />
| $C<br />
| bgcolor=FFDDDD | $06A || 16884.6 Hz || C-10 +14.5c<br />
| bgcolor=DDDDFF | $062 || 16965.4 Hz || C-10 +22.7c<br />
|-<br />
| $D<br />
| bgcolor=FFDDDD | $054 || 21306.8 Hz || E-10 +17.2c<br />
| bgcolor=DDDDFF | $04E || 21315.5 Hz || E-10 +17.9c<br />
|-<br />
| $E<br />
| bgcolor=FFDDDD | $048 || 24858.0 Hz || G-10 -15.9c<br />
| bgcolor=DDDDFF | $042 || 25191.0 Hz || G-10 +7.11c<br />
|-<br />
| $F<br />
| bgcolor=FFDDDD | $036 || 33143.9 Hz || C-11 -17.9c<br />
| bgcolor=DDDDFF | $032 || 33252.1 Hz || C-11 -12.2c<br />
|}<br />
(Deviation from note is given in cents, which are defined as 1/100th of a semitone.)<br />
<br />
Note that on PAL systems, the pitches at $4 and $C appear to be incorrect with respect to their intended A-440 tuning scheme<ref>[http://forums.nesdev.org/viewtopic.php?p=94079#p94079 Forum post]: PAL DPCM frequency table contains 2 errors.</ref>.<br />
<br />
=== Memory reader ===<br />
<br />
When the sample buffer is emptied, the memory reader fills the sample buffer with the next byte from the currently playing sample. It has an address counter and a bytes remaining counter.<br />
<br />
When a sample is (re)started, the current address is set to the sample address, and bytes remaining is set to the sample length.<br />
<br />
Any time the sample buffer is in an empty state and bytes remaining is not zero (including just after a write to $4015 that enables the channel, regardless of where that write occurs relative to the bit counter mentioned below), the following occur:<br />
<br />
* The [[CPU]] is stalled for 1-4 CPU cycles to read a sample byte. The exact cycle count depends on many factors and is described in detail in the [[DMA]] article.<br />
* The sample buffer is filled with the next sample byte read from the current address, subject to whatever [[MMC|mapping hardware]] is present.<br />
* The address is incremented; if it exceeds $FFFF, it is wrapped around to $8000.<br />
* The bytes remaining counter is decremented; if it becomes zero and the loop flag is set, the sample is restarted (see above); otherwise, if the bytes remaining counter becomes zero and the IRQ enabled flag is set, the interrupt flag is set.<br />
<br />
At any time, if the interrupt flag is set, the [[CPU|CPU's IRQ line]] is ''continuously'' asserted until the interrupt flag is cleared.<br />
The processor will continue on from where it was stalled.<br />
<br />
=== Output unit ===<br />
<br />
The output unit continuously outputs a 7-bit value to the [[APU Mixer|mixer]]. It contains an 8-bit right shift register, a bits-remaining counter, a 7-bit output level (the same one that can be loaded directly via $4011), and a silence flag.<br />
<br />
The bits-remaining counter is updated whenever the [[APU Misc|timer]] outputs a clock, regardless of whether a sample is currently playing. When this counter reaches zero, we say that the output cycle ends. The DPCM unit can only transition from silent to playing at the end of an output cycle.<br />
<br />
When an output cycle ends, a new cycle is started as follows:<br />
* The bits-remaining counter is loaded with 8.<br />
* If the sample buffer is empty, then the silence flag is set; otherwise, the silence flag is cleared and the sample buffer is emptied into the shift register.<br />
<br />
When the timer outputs a clock, the following actions occur in order:<br />
# If the silence flag is clear, the output level changes based on bit 0 of the shift register. If the bit is 1, add 2; otherwise, subtract 2. But if adding or subtracting 2 would cause the output level to leave the 0-127 range, leave the output level unchanged. This means subtract 2 only if the current level is at least 2, or add 2 only if the current level is at most 125.<br />
# The right shift register is clocked.<br />
# As stated above, the bits-remaining counter is decremented. If it becomes zero, a new output cycle is started.<br />
<br />
''Nothing can interrupt a cycle; every cycle runs to completion before a new cycle is started.''<br />
<br />
== Conflict with controller and PPU read ==<br />
<br />
On the NTSC NES and Famicom, if a new sample byte is fetched from memory at the same time the program is reading the [[Standard controller|controller]] through $4016/4017, a conflict occurs corrupting the data read from the controller. Programs which use DPCM sample playback will normally use a redundant [[Controller Reading|controller read]] routine to work around this defect.<br />
<br />
A similar problem occurs when reading data from the PPU through $2007, or polling $2002 for vblank.<br />
<br />
=== Likely internal implementation of the read ===<br />
<br />
The following is speculation, and thus not necessarily 100% accurate, but it does accurately predict observed behavior.<br />
<br />
The 6502 cannot be pulled off of the bus normally. The 2A03 DMC gets around this by pulling RDY low internally. This causes the CPU to pause during the next read cycle, until RDY goes high again. The DMC unit holds RDY low for 4 cycles. The first three cycles it idles, as the CPU could have just started an interrupt cycle, and thus be writing for 3 consecutive cycles (and thus ignoring RDY). On the fourth cycle, the DMC unit drives the next sample address onto the address lines, and reads that byte from memory. It then drives RDY high again, and the CPU picks up where it left off.<br />
<br />
This matters because on NTSC NES and Famicom, it can interfere with the expected operation of any register where reads have a side effect: the controller registers ($4016 and $4017), reads of the PPU status register ($2002), and reads of VRAM/VROM data ($2007) if they happen to occur in the same cycle that the DMC unit pulls RDY low.<br />
<br />
For the controller registers, this can cause an extra rising clock edge to occur, and thus shift an extra bit out. For the others, the PPU will see multiple reads, which will cause extra increments of the address latches, or clear the vblank flag.<br />
<br />
This problem has been fixed on the 2A07 and PAL NES is exempt of this bug.<br />
<br />
== Usage of DMC for syncing to video ==<br />
<br />
DMC IRQs can be used for timed video operations. The following method was discussed on the forum in 2010.<ref>[http://forums.nesdev.org/viewtopic.php?t=6521 Forum thread]: DMC IRQ as a video timer.</ref><br />
<br />
=== Concept ===<br />
<br />
The NES hardware only has limited tools for syncing the code with video rendering. The VBlank NMI and sprite 0 hit are the only two reasonably reliable flags that can be used, so only 2 synchronizations per frame can be done easily. In addition, only the VBlank NMI can trigger an interrupt; the sprite 0 hit flag has to be polled, potentially wasting a lot of CPU cycles.<br />
<br />
However, the DMC channel can hypothetically be used for syncing with video instead of using it for sound. Unfortunately it's a bit complicated, but used correctly, it can function as a crude scanline counter, eliminating the need for an advanced mapper.<br />
<br />
The DMC's timing is completely separate from the video. The DMC's timer is always running, and samples can only start every 8 clock cycles. However, because the DMC's timer isn't synchronized to the PPU in any way, these 8-clock boundaries occur on different scanlines each frame.<br />
<br />
Here are the steps to achieve stable timing:<br />
<br />
* At a fixed point in video rendering (we'll use the start of vblank as an example), a dummy single-byte sample at rate $F is started. Due to a hardware quirk†, the sample needs to be started three times in a row like this:<br />
<br />
<pre><br />
sei<br />
lda #$10 <br />
sta $4015 <br />
sta $4015 <br />
sta $4015 <br />
cli<br />
</pre><br />
<br />
* The amount of cycles before a DMC IRQ happens is then measured (either using an actual IRQ, or by polling $4015).<br />
** At rate $F, there are 54 CPU cycles between clocks, so there are 432 CPU cycles (432 × 3 ÷ 341 = about 3.8 scanlines) between boundaries.<br />
* The main sample that will be used for the timing is then started (please refer to the table below to have sample lengths for various waiting times)<br />
* When the main IRQ happens, the measurement from before is retrieved, and a timing loop with variable delay is used. In order to synchronize with vblank, after a DMC IRQ we should wait 432 CPU cycles minus the time we measured.<br />
†'''Note:''' The hardware quirk mentioned above deals with how DMC IRQs are generated. Basically, the IRQ is generated when the last '''byte''' of the sample is '''read''', '''not''' when the last ''sample'' of the sample ''plays''. The sample buffer sometimes has enough time to empty itself between writes to $4015, meaning your next write to $4015 will trigger an immediate IRQ. Fortunately, writing to $4015 three times will avoid this issue.<br />
<br />
Still using vblank as an example, the measurement tells how far into the 8-clock boundary vblank occurred, and by delaying after a DMC IRQ, we perform a raster effect at the same point within the 8-clock boundary, aligning it with vblank. By performing this same method each frame, the raster effect will have a reasonably stable timing to it. As a bonus, since mostly using IRQs are being used, the CPU is free to do something else, instead of waiting in a timed loop.<br />
<br />
It's possible to use more than one IRQ per frame - but the ''measurement'' part needs to be done at the ''same time'' within each frame, before the usage of any IRQ.<br />
<br />
Only a single split-point per IRQ is possible, with the shortest IRQ being 3.8 scanlines. For split points closer than this amount, timed code has to be used.<br />
<br />
In order to remain silent, samples should be made up of all $00 bytes, and $00 should have been previously written to $4011. Otherwise, audio will unintentionally be created. This ''is'' a sound channel, after all.<br />
<br />
=== Timing table ===<br />
<br />
This table converts sample length in scanline length (all values are rounded to the higher integer).<br />
<br />
<pre><br />
NTSC Rate <br />
Length $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $a $b $c $d $e $f <br />
---------------------------------------------------------------------------------------------------- <br />
1-byte (8 bits) 31 27 24 23 21 18 16 16 14 12 10 10 8 6 6 4 <br />
17-byte (136 bits) ** ** ** ** ** ** ** ** 228 192 170 154 127 101 87 65 <br />
33-byte (264 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** 196 168 126 <br />
49-byte (392 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 187 <br />
<br />
PAL Rate <br />
Length $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $a $b $c $d $e $f <br />
---------------------------------------------------------------------------------------------------- <br />
1-byte (8 bits) 30 27 24 23 21 18 16 15 14 12 10 9 8 6 5 4 <br />
17-byte (136 bits) ** ** ** ** ** ** ** ** 225 189 169 151 126 100 85 64 <br />
33-byte (264 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** 194 164 124 <br />
49-byte (392 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 184<br />
</pre><br />
<br />
=== Number of scanlines to wait table ===<br />
<br />
This table gives the best sample length and frequency combinations for all possible scanlines interval to wait. They are best because they are where the CPU will have to kill the least time. However, it's still possible to use options to wait for fewer lines and kill more time during the interrupt before the video effect.<br />
<br />
Because a PAL interrupt will always happen about the same time or a bit sooner than a NTSC interrupt, the NTSC table will be used to set the "best" setting here :<br />
<br />
<pre><br />
Scanlines Best opt. for IRQ <br />
<br />
1-3 Timed code <br />
4-5 Length $0, rate $f <br />
6-7 Length $0, rate $d <br />
8-9 Length $0, rate $c <br />
10-11 Length $0, rate $a <br />
12-13 Length $0, rate $9 <br />
14-15 Length $0, rate $8 <br />
16-17 Length $0, rate $6 <br />
18-20 Length $0, rate $5 <br />
21-22 Length $0, rate $4 <br />
23 Length $0, rate $3 <br />
24-26 Length $0, rate $2 <br />
27-30 Length $0, rate $1 <br />
31-64 Length $0, rate $0 <br />
65-86 Length $1, rate $f <br />
87-100 Length $1, rate $e <br />
101-125 Length $1, rate $d <br />
126 Length $2, rate $f <br />
127-153 Length $1, rate $c <br />
154-167 Length $1, rate $b <br />
168-169 Length $2, rate $e <br />
170-186 Length $1, rate $a <br />
187-191 Length $3, rate $f <br />
192-195 Length $1, rate $9 <br />
196-227 Length $2, rate $d <br />
228-239 Length $1, rate $8<br />
</pre><br />
<br />
== References ==<br />
<references /></div>Fiskbithttps://www.nesdev.org/w/index.php?title=DMA&diff=21665DMA2024-03-15T15:55:19Z<p>Fiskbit: /* References */ Brings over references from the defunct APU DMC cycle count section.</p>
<hr />
<div>The 2A03 contains a pair of DMA units, one for copying sprite data to PPU [[OAM]] and the other for copying DPCM sample data to the APU's [[APU DMC|DMC]] sample buffer. DMA is required for DPCM playback, and it is difficult to fill OAM without DMA. Unfortunately, DMC DMA can also result in data loss when reading registers with side effects, such as the joypads.<br />
<br />
==Summary==<br />
* The CPU alternates between cycles on which DMA can get (read) and cycles on which DMA can put (write). These are the first and second halves of APU cycles, respectively. At power-on, whether the first CPU cycle is get or put is random.<br />
* If DMA tries to get on a put cycle, it waits and tries again next cycle. This wait is called an alignment cycle.<br />
* DMA can only halt on CPU read cycles. On write cycles, the halt fails and the DMA unit tries again next CPU cycle, repeating until successful.<br />
* OAM DMA halts the CPU, performs an optional alignment cycle, and then gets and puts 256 times, taking 513 or 514 cycles. It attempts to halt on the first CPU cycle after the $4014 write.<br />
* DMC DMA halts the CPU, performs a dummy cycle and an optional alignment cycle, and then gets once, taking 3 or 4 cycles. <br />
* The first, "load" DMC DMA after the $4015 write attempts to halt on the get cycle during the 2nd following APU cycle. The other, "reload" DMC DMAs attempt to halt on a put cycle. Failed halts try again on the next CPU cycle, repeating until successful.<br />
* The DMC DMA get takes precedence over OAM DMA get, delaying it, but the DMA cycles otherwise overlap, reducing the total cycle cost. This delay can force OAM DMA to add an alignment cycle.<br />
* DMC DMA has [[#Bugs|bugs triggered by stopping the sample at specific times]].<br />
* DMC DMA can [[#Register conflicts|corrupt joypad and PPUDATA ($2007) reads and cause extraneous reads of $4015-4017]].<br />
<br />
==Cadence==<br />
The DMA units cannot just read or write on any cycle as they wish. Instead, they alternate between '''get''' cycles where they can read and '''put''' cycles where they can write. If they need to perform an action that is not permitted on the current cycle, they wait.<br />
<br />
Get and put cycles are aligned to the first and second halves of the APU clock, respectively (called apu_clk1 and apu_clk2 in Visual2A03). While these cycles are sometimes described as even and odd CPU cycles, this is not accurate because the CPU and APU randomly power into either of 2 alignments relative to each other. Therefore, get and put may occur on different CPU cycle parities across different power cycles.<br />
<br />
==Behavior==<br />
During the DMA process, the CPU is halted and the 2A03's address and data lines are used for data transfer. The process involves a combination of no-operation cycles and access cycles. No-operation cycles come in 3 equivalent types: the halt cycle, a DMC-only dummy cycle, and an optional alignment cycle.<br />
<br />
When DMA is scheduled, the associated DMA unit attempts to halt the CPU. The CPU only allows this on read cycles. If the CPU is writing, it ignores the halt and the DMA unit waits until the next cycle to try again, repeating until successful. Delays of up to 3 cycles are possible, with read-modify-write instructions having 2 consecutive writes and interrupts having 3. The halting process itself takes 1 CPU cycle, during which no useful work is done.<br />
<br />
Once the CPU is halted, the DMA unit may need to perform some amount of non-access setup, taking up to 2 cycles. The exact timing of when DMA is scheduled and what kind of setup it needs depends on the type of DMA.<br />
<br />
The CPU is halted using its internal RDY input. When RDY is deasserted, the 6502 core repeats the last read cycle indefinitely, making no forward progress nor handling interrupts. On 2A03 CPUs, these repeated reads are externally visible on any no-operation DMA cycle, causing data loss if reading a register with side effects. On 2A07 CPUs, it is suspected that a different address (perhaps the DMA address) is on the bus, instead, during all no-operation cycles. See [[#Register conflicts|Register conflicts]] for more information.<br />
<br />
When the DMA process completes, the CPU performs the read it attempted when halted.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - General behavior</div><br />
<div class="mw-collapsible-content"><br />
* DMA halts normally:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA halt is delayed by writes:<br />
CPU writes <- DMA attempts to halt<br />
CPU writes <- DMA attempts to halt<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA has a non-access cycle:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) CPU reads from address A <- DMA does not read or write<br />
(halted) DMA accesses address B<br />
CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===OAM DMA===<br />
-----<br />
OAM DMA copies 256 bytes from a CPU page to PPU OAM via the [[PPU_registers#OAMDATA|OAMDATA ($2004)]] register. It is triggered by writing the page number (the high byte of the address) to [[PPU_registers#OAMDMA|OAMDMA ($4014)]]. OAM DMA is scheduled to halt the CPU on the first cycle after the register write. In the common case, it performs a halt cycle, an optional alignment cycle, and 256 get/put pairs. <br />
<br />
The 256 get/put pairs copy forward from the start of the page. Because DMA can only read on get cycles, an alignment cycle performing no useful work may be required before being able to read. All together, OAM DMA on its own takes 513 or 514 cycles, depending on whether alignment is needed.<br />
<br />
OAM DMA will copy from the page most recently written to $4014. This means that read-modify-write instructions such as INC $4014, which are able to perform a second write before the CPU can be halted, will copy from the second page written, not the first.<br />
<br />
OAM DMA has a lower priority than DMC DMA. If a DMC DMA get occurs during OAM DMA, OAM DMA is briefly paused. (See [[#DMC DMA during OAM DMA|DMC DMA during OAM DMA]])<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* Alignment is not needed:<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Alignment is needed:<br />
(put) CPU writes to $4014<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===DMC DMA===<br />
-----<br />
DMC DMA copies a single byte to the DMC unit's sample buffer. This occurs automatically after the DMC enable bit, bit 4, of the [[APU#Status_($4015)|sound channel enable register ($4015)]] is set to 1, which starts DPCM sample playback using the current DMC settings in [[APU_DMC#Overview|registers $4010-4013]]. DMC DMA is scheduled when all of DPCM playback is enabled, there are bytes left in the sample, and the sample buffer is empty (see [[APU_DMC#Memory_reader|Memory reader]] and [[APU_DMC#Output_unit|Output unit]]). In the common cases, DMC DMA performs a halt cycle, a dummy cycle, an optional alignment cycle, and a get.<br />
<br />
The exact timing depends on the type of DMC DMA. There are two types: load and reload. Load DMAs occur after $4015 D4 is set, but only if the sample buffer is empty. They are scheduled to halt the CPU on a get cycle during the 2nd APU cycle after the write (that is, the 3rd or 4th CPU cycle). Reload DMAs occur in response to the sample buffer being emptied. Unlike load DMAs, they are scheduled to halt the CPU on a put cycle.<br />
<br />
After the halt, DMC DMA always performs a dummy cycle where no work is done. If the next cycle is not a get cycle, then a cycle will be spent on alignment. Then the DMA read is performed.<br />
<br />
DMC DMA normally takes 3 or 4 cycles, depending on whether alignment is needed. Because load and reload DMAs schedule on different cycle types, load DMAs take 3 cycles and reload DMAs take 4 unless the halt is delayed by an odd number of cycles. However, bugs can cause additional cycles; see [[#Bugs|Bugs]] below.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA</div><br />
<div class="mw-collapsible-content"><br />
* Load DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Load DMA (delayed 1 cycle):<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA:<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 1 cycle):<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 2 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 3 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
====Bugs====<br />
DMC DMA suffers from two bugs<ref>[https://forums.nesdev.org/viewtopic.php?p=250170#p250170 Forum post:] Fiskbit's manual DMA test suite</ref><ref>[https://forums.nesdev.org/viewtopic.php?p=275734#p275734 Forum post:] Fiskbit's explicit and implicit stop tests</ref> related to sample playback stopping around the time [[APU_DMC#Output_unit|a DMC output cycle ends]], which is what empties the sample buffer and triggers a reload DMA. This can happen explicitly, where the sample is stopped by clearing $4015 D4, or implicitly, where a non-looping 1-byte sample is started while the sample buffer is empty shortly before a reload DMA would schedule. Implicit stops require this type of sample because the load DMA for the first byte when the sample buffer is empty is the only way to implicitly end the sample just before a reload DMA; longer samples will instead be ended by the reload DMA itself, as normal.<br />
<br />
When sample playback is stopped during the APU cycle before a reload DMA would schedule (that is, on the 2nd or 3rd CPU cycle before the halt attempt), the DMA starts, but is aborted after a single cycle. If the halt is delayed due to a write cycle, the aborted DMA doesn't occur at all. This aborted DMA schedules regardless of how playback was stopped, whether explicitly or implicitly. In the implicit case, the write to begin the sample will normally be the 4th APU cycle before the reload DMA would schedule (8th or 9th CPU cycle before).<br />
<br />
On RP2A03H and late RP2A03G CPUs, when playback is stopped implicitly on the same APU cycle that a reload DMA would schedule (that is, the 1st CPU cycle before the halt attempt), an unexpected reload DMA occurs from the same address. This extra byte goes into the sample buffer and is played after the first byte, as with any normal fetch. On RP2A03G CPUs, this bug was introduced sometime in 1990; earlier chips are unaffected.<br />
<br />
It is not known whether 2A07 CPUs are affected by these bugs. Some clone hardware is known to be affected, and behavior on affected clones may differ from official CPUs. For example, UA6527P-based clones feature both the aborted DMA and unexpected DMA bugs, but samples take 1 APU cycle longer to end than on official CPUs, so to trigger these bugs with implicit stops, the sample-ending byte must be fetched 1 APU cycle earlier.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA bugs</div><br />
<div class="mw-collapsible-content"><br />
* Explicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC disabled<br />
(put) / during this APU cycle <- DMC disabled<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Implicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address C <- DMA halt cycle<br />
(get) CPU reads from address C <- CPU resumes execution<br />
<br />
* Implicit-stop unexpected DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
The implicit-stop aborted DMA can be prevented with carefully placed write cycles. This can be necessary for synchronized code, where the aborted DMA's odd number of cycles can invert cycle parity. The following code synchronizes to a put cycle and uses precise write cycles to prevent any aborted DMA that may occur:<br />
STx $4015 ; Initiate DMC DMA.<br />
STx zp ; Force load DMA to the 4th cycle.<br />
; (If on a UA6527P-based clone, place a NOP here.)<br />
STx zp ; Override the aborted DMA.<br />
; The first cycle of the next instruction is a put cycle.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - aborted DMA workaround</div><br />
<div class="mw-collapsible-content"><br />
* Implicit-stop aborted DMA bypass (write on get):<br />
(get) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) CPU reads<br />
(get) CPU reads<br />
(put) CPU writes<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
<br />
* Implicit-stop aborted DMA bypass (write on put):<br />
(put) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
</div></div></div><br />
<br />
===DMC DMA during OAM DMA===<br />
DMC and OAM use independent DMA units that only interact when both attempt to access memory on the same cycle. When accesses collide, DMC DMA is allowed to run and OAM DMA is paused, trying again on the next cycle. This can cause OAM DMA to have to perform an additional alignment cycle before continuing. No-operation cycles are allowed to overlap with each other and with access cycles, allowing cycles to be saved.<br />
<br />
In the common case, DMC DMA occurring during OAM DMA will cost only 2 cycles: 1 cycle for the DMC DMA get and then 1 cycle for OAM DMA to align back to a get. However, if DMC DMA occurs at the end of OAM DMA, it can take 1 or 3 cycles. If it schedules for the second-to-last put, its get will occur on the first cycle after OAM DMA, taking just 1 cycle total. If it schedules for the last put, it will instead extend 3 cycles beyond the end of OAM DMA.<br />
<br />
OAM DMA is sometimes used to synchronize code to avoid conflicts with DMC DMA when reading hardware registers, but because DMC DMA takes an odd number of cycles if it lands at the end, synchronization is not guaranteed.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA during OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA at the start of OAM DMA (write on get), taking 2 cycles<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xx00 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
<br />
* DMC DMA at the start of OAM DMA (write on put), taking 2 cycles<br />
(put) CPU writes to $4014 <- DMC DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA dummy cycle, OAM DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from $xx00<br />
(halted) (put) OAM DMA writes to $2004<br />
...<br />
<br />
* DMC DMA in the middle of OAM DMA, taking 2 cycles<br />
...<br />
(halted) (get) OAM DMA reads from address C<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from address C+1 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from address C+2<br />
...<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 1 cycle<br />
...<br />
(halted) (get) OAM DMA reads from $xxFE<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xxFF <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 3 cycles<br />
...<br />
(halted) (get) OAM DMA reads from $xxFF<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMC DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
==Register conflicts==<br />
On the 2A03, while the CPU is halted, it repeats the read cycle on which it was halted during every no-operation DMA cycle (that is, when the DMA units are not reading or writing). If the CPU was reading a register with side-effects, this can cause data to be lost. While this isn't realistically a problem with OAM DMA because of its particular timing constraints, it is a very real problem with DMC DMA that must usually be worked around. Example registers include PPUSTATUS ($2002), PPUDATA ($2007), and sound status ($4015). When conflicting with DMC DMA, these will see 2 or more extra reads. (Note that $2007 reads on adjacent cycles may have unexpected behavior.)<br />
<br />
Most frequently, these DMC DMA conflicts occur with joypad reads, though the mechanism is slightly different. Joypads are clocked via direct lines from the CPU, called joypad 1 /OE and joypad 2 /OE, rather than going over the address bus. These output enables remain asserted the entire CPU cycle and even across adjacent cycles if they're both reading the same joypad register. Therefore, controllers only see a single read for each contiguous set of reads of a joypad register.<br />
<br />
The console type affects joypad extra-read behavior. On the RF Famicom, additional hardware outside the 2A03 only passes joypad 1 /OE and joypad 2 /OE through during one half of the clock cycle, meaning the joypad sees a clock on every single CPU read cycle rather than just every contiguous set<ref>[https://forums.nesdev.org/viewtopic.php?p=275946#p275946 Forum post:] lidnariq's RF Famicom joypad clocking explanation</ref>. The RF Famicom is the only console known to behave this way. The AV Famicom and NES-001 are confirmed to use the per-contiguous-set behavior.<ref>[https://forums.nesdev.org/viewtopic.php?p=275468#p275468 Forum post:] Fiskbit's joypad read cycle breakdown</ref><br />
<br />
This is further complicated by esoteric behavior regarding how 2A03 registers are activated: instead of checking the full 2A03 address bus, it checks bits 4-0 from the 2A03 address bus and bits 15-5 from the 6502 core. The 6502 core keeps the same address while halted, so if it was reading from $4000-401F, the DMA address can unintentionally activate 2A03 registers. This can lead to bus conflicts and an extra read from the other joypad, and can even prevent an extra read of the current joypad.<ref>[https://forums.nesdev.org/viewtopic.php?p=275132#p275132 Forum post:] Fiskbit's APU register activation test</ref><br />
<br />
The 2A07 fixes these extra read problems, but the mechanism is not yet understood. Experimentally, the CPU still performs a read on the halting cycle; if OAM DMA is done from the $4000 page, the open bus value used by the OAM DMA is the opcode of the instruction following the $4014 write. This means that 6502 core reads still occur when halted, at least on the first cycle. Like on NTSC, this DMA also does not trigger 2A07 registers if the 6502 core is not reading from $4000-401F. Unlike NTSC, reading a joypad register when DMA reads an address that matches the other joypad register in its low 5 bits does not clock the other joypad.<br />
<br />
Workarounds exist for this issue. Most commonly, [[Controller_reading_code#DPCM_Safety_using_Repeated_Reads|joypads are read multiple times]] until the same result is seen twice in row, reducing or eliminating the chance of accepting corrupted data. However, any collisions during this time may corrupt the DPCM data, and this strategy is not suitable for all affected registers. Alternatively, [[Controller_reading_code#DPCM_Safety_using_OAM_DMA|reads synchronized using OAM DMA]] can ensure a collision never happens, but this enforces strict timing constraints on the code and has numerous caveats, particularly for functions longer than one DMC output cycle (sample byte period).<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - Register conflicts</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA collides with $2007 read (3 extra reads)<br />
(halted) (put) CPU reads from $2007 <- DMA halt cycle<br />
(halted) (get) CPU reads from $2007 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $2007 <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from $2007 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 ($4016) read (1 or 3 extra reads)<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C000<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (0 or 4 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4016.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C016 and $4016<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (1 extra read of JOYPAD2, 1 or 3 extra of JOYPAD1)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4017.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C017 and $4017<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
*DMC DMA collides with JOYPAD1 read (1 or 3 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4015.<br />
** This causes the 2A03 to read $4015 and ignore the DMA value on the external data bus.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C015, 2A03 reads from $4015 internally<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
</div></div></div><br />
<br />
==References==<br />
:* [https://github.com/emu-russia/breaks/blob/master/BreakingNESWiki_DeepL/APU/dma.md BreakingNESWiki:] DMA circuit analysis<br />
:* [https://forums.nesdev.org/viewtopic.php?t=14120 Forum post:] Disch's OAM/DMC DMA test results<br />
:* [https://forums.nesdev.org/viewtopic.php?p=62690#p62690 Forum post:] Blargg's DMA tests<br />
:* [https://forums.nesdev.org/viewtopic.php?p=231604#p231604 Forum post:] Fiskbit's aligned controller read tests<br />
:* [https://forums.nesdev.org/viewtopic.php?p=95703#95703 Forum post:] cpow's Visual 2A03 DMC vs OAM DMA analysis<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=Controller_reading_code&diff=21664Controller reading code2024-03-15T15:54:37Z<p>Fiskbit: Adds a cycle count table for various DMC DMA cases to the synced reads section. This is more relevant and less misleading here than on the APU DMC page.</p>
<hr />
<div>This page contains example code for reading the [[NES controller]].<br />
<br />
See also: [[Controller reading]]<br />
<br />
== Controller Reading Code ==<br />
<br />
=== Basic Example ===<br />
<br />
This is a tutorial example of the bare minimum needed to read the controller.<br />
It will explain the basic principles in detail, but once understood, you may wish to continue to the [[#Standard Read for 2 Controllers and Famicom|Standard Read]] example that follows,<br />
as a more complete and ready-to-use code example.<br />
<br />
This code describes an efficient method of reading the [[standard controller]] using [http://cc65.github.io/cc65/ ca65] syntax.<br />
<br />
The result byte ''buttons'' should be placed in zero page to save a cycle each time through the loop.<br />
<pre><br />
; we reserve one byte for storing the data that is read from controller<br />
.zeropage<br />
buttons .res 1<br />
</pre><br />
<br />
When reading from ''JOYPAD*'' what is read might be different from $01/$00 for various reasons. (See [[Controller reading]].) In this code the only concern is bit 0 read from ''JOYPAD*.''.<br />
<pre><br />
JOYPAD1 = $4016<br />
JOYPAD2 = $4017<br />
</pre><br />
<br />
This is the end result that will be stored in ''buttons''. '''1''' if the button was pressed, '''0''' otherwise.<br />
<br />
{| class="wikitable" style="text-align:center;"<br />
|-<br />
! bit<br />
| &nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;<br />
| &nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;<br />
|-<br />
! button<br />
| A<br />
| B<br />
| Select<br />
| Start<br />
| Up<br />
| Down<br />
| Left<br />
| Right<br />
|}<br />
<br />
This subroutine takes 132 cycles to execute but ignores the Famicom expansion controller.<br />
Many controller reading subroutines use the X or Y register to count 8 times through the loop.<br />
But this one uses a more clever [[wikipedia:Ring counter|ring counter]] technique: $01 is loaded into the result first, and once eight bits are shifted in, the 1 bit will be shifted out, terminating the loop.<br />
<pre><br />
; At the same time that we strobe bit 0, we initialize the ring counter<br />
; so we're hitting two birds with one stone here<br />
readjoy:<br />
lda #$01<br />
; While the strobe bit is set, buttons will be continuously reloaded.<br />
; This means that reading from JOYPAD1 will only return the state of the<br />
; first button: button A.<br />
sta JOYPAD1<br />
sta buttons<br />
lsr a ; now A is 0<br />
; By storing 0 into JOYPAD1, the strobe bit is cleared and the reloading stops.<br />
; This allows all 8 buttons (newly reloaded) to be read from JOYPAD1.<br />
sta JOYPAD1<br />
loop:<br />
lda JOYPAD1<br />
lsr a ; bit 0 -> Carry<br />
rol buttons ; Carry -> bit 0; bit 7 -> Carry<br />
bcc loop<br />
rts<br />
</pre><br />
<br />
Continue to the next example for a more complete read routine that handles both controllers and the standard Famicom expansion controllers.<br />
<br />
=== Standard Read for 2 Controllers and Famicom ===<br />
<br />
Adding support for controllers on the Famicom's DA15 expansion port and for player 2's controller is straightforward. Something similar to the following routine is used in most Famicom games.<br />
Even though the expansion port is unused on the NES, the unconnected bit will read as 0, so this solution works safely with both Famicom and NES hardware.<br />
<pre><br />
.zeropage<br />
buttons: .res 2 ; space for 2 reads<br />
<br />
.code<br />
readjoyx2:<br />
ldx #$00<br />
jsr readjoyx ; X=0: read controller 1<br />
inx<br />
; fall through to readjoyx below, X=1: read controller 2<br />
<br />
readjoyx: ; X register = 0 for controller 1, 1 for controller 2<br />
lda #$01<br />
sta JOYPAD1<br />
sta buttons, x<br />
lsr a<br />
sta JOYPAD1<br />
loop:<br />
lda JOYPAD1, x<br />
and #%00000011 ; ignore bits other than controller<br />
cmp #$01 ; Set carry if and only if nonzero<br />
rol buttons, x ; Carry -> bit 0; but 7 -> Carry<br />
bcc loop<br />
rts<br />
</pre><br />
<br />
If playing DPCM samples, there is an additional reread step to prevent errors ([[#DPCM Safety using Repeated Reads|see below]]).<br />
<br />
Note that the <tt>and</tt> to ignore bits is not optional, as the upper bits of <tt>JOYPAD1</tt> read are not guaranteed to be 1 or 0<ref>[[Controller_reading#Unconnected_data_lines_and_open_bus|Controller reading: Unconnected data lines and open bus]]</ref>.<br />
<br />
=== Alternative 2 Controllers Read ===<br />
<br />
Alternatively, we could combine both controller reads into 1 loop with a single strobe, though this routine is not safe to use with DPCM samples playing ([[#DPCM Safety using Repeated Reads|see below]]).<br />
<pre><br />
.zeropage<br />
buttons: .res 2<br />
<br />
.code<br />
readjoy2:<br />
lda #$01<br />
sta JOYPAD1<br />
sta buttons+1 ; player 2's buttons double as a ring counter<br />
lsr a<br />
sta JOYPAD1<br />
loop:<br />
lda JOYPAD1<br />
and #%00000011<br />
cmp #$01<br />
rol buttons+0<br />
lda JOYPAD2<br />
and #%00000011<br />
cmp #$01<br />
rol buttons+1<br />
bcc loop<br />
rts<br />
</pre><br />
<br />
=== DPCM Safety ===<br />
-----<br />
<br />
The NTSC CPU has a bug where the [[DMA]] that fetches DPCM sample data for the [[APU DMC|APU's DMC channel]] can cause extra reads of the joypads. This is fixed on PAL. For standard controllers, this bug results in a bit being deleted from the controller's serial report, causing the following buttons to be off-by-one and usually resulting in the right button appearing to be pressed. Software cannot directly detect that this bug has happened, so controller reading code in games using sampled audio has to be resilient against it. There are currently two approaches for dealing with this problem, each with significant pros and cons.<br />
<br />
Note that both approaches share some limitations:<br />
* They may become unsafe if interrupted by NMI or IRQ.<br />
* Poor support across most emulators can make it hard to know if the code works correctly on hardware.<br />
* Using third party controllers may make testing harder: official standard controllers shift in 1's on extra reads that cause obvious errant right presses, while third party controllers may shift in 0's.<br />
* It is possible for joypad state to corrupt even if the controller reading code works as intended. Any read from $4000-401F provides an opportunity for DMC DMA to trigger a joypad read, and this can cause controllers with state that is slow or impossible to recover (e.g. [[Arkanoid controller]]) to lose that state before the controllers are intentionally read. Some sound engines cause such reads by doing indexed stores to sound registers. For controllers with normal strobe behavior where the full current state is immediately loaded on strobe, this is not a problem.<br />
<br />
Neither approach is a one-size-fits-all solution; there are cases where one or the other solution does not work.<br />
<br />
==== DPCM Safety using Repeated Reads ====<br />
<br />
The most common technique, as seen in ''Super Mario Bros. 3''<ref>[//forums.nesdev.org/viewtopic.php?p=151720#p151720 Super Mario Bros. 3 controller reread method]</ref> and other games, will read each controller twice, but in the event of a mismatch it will keep re-reading the controller until two results in a row are the same.<br />
<pre><br />
readjoy2_safe:<br />
ldx #$00<br />
jsr readjoyx_safe ; X=0: safe read controller 1<br />
inx<br />
; fall through to readjoyx_safe, X=1: safe read controller 2<br />
<br />
readjoyx_safe:<br />
jsr readjoyx<br />
reread:<br />
lda buttons, x<br />
pha<br />
jsr readjoyx<br />
pla<br />
cmp buttons, x<br />
bne reread<br />
rts<br />
</pre><br />
<br />
Note that the time between the start of one read and the end of the next read must be less than the length of the fastest DMC fetch period minus 4 (428 cycles). This is because multiple bit deletions could cause both passes to result in the same incorrect data. For this reason, it is normal to read controllers one at a time with this method, rather than attempting both at once. (Note: <code>readjoy2</code> above takes too long to be suitable.) [[Game bugs|''Gimmick!'' has such a bug]] resulting from trying to read both at once.<br />
<br />
Most often a controller will be read 2 times, and 3 or 4 in the case of a DPCM corruption, or the player pressing a button during the read. With the assistance of tools, a malicious controller input could change the buttons on every read, holding it in this reread loop indefinitely<ref>[https://arstechnica.com/gaming/2016/07/how-to-beat-super-mario-bros-3-in-less-than-a-second/ Ars Technica: How to beat Super Mario Bros. 3 in less than a second]</ref><ref>https://tasvideos.org/6466S Tool-Assisted Speedrun of Super Mario Bros. 3 which first demonstrated abusing controller reread routines.</ref>, but this is generally not an important edge case to account for.<br />
<br />
This approach to DPCM safety has these benefits:<br />
* The code is easy to understand and modify.<br />
* It is position-independent: branching across page boundaries does not inherently break it, and it can be done at any time in the frame.<br />
* It works in all emulators, even if they don't implement the bug correctly or at all.<br />
It also has these drawbacks:<br />
* Repeated reads cannot be used for controllers that lose state on reads (e.g. [[SNES mouse]]), take a long time before data is available to read again (e.g. [[Arkanoid controller]]), or have too much data to read twice within the cycle budget (e.g. [[Famicom Network Controller]]).<br />
* It can be hard to know if the code is safe:<br />
** The budget limitations are not obvious because of obscure edge cases with the bug. All joypad reads for 2 complete passes must finish within one DMC period minus 4 (usually 428 cycles). Reading both controllers in a single pass takes too long; they must be handled individually.<br />
** Hardware differences can make real hardware testing difficult: the bug behaves one way on the AV Famicom and NES, and another way on other Famicom models. The Famicom behavior may mitigate the bug when using repeated reads.<br />
** Even most accurate emulators don't emulate all the ways repeated reads can fail. Mesen v2 does and is recommended.<br />
* This approach does not prevent the bug, it merely works around it, so other negative side effects of the bug still happen:<br />
** The sample byte read by the APU can be corrupted when the bug occurs. However, it is difficult to hear this corruption.<br />
** The APU's frame IRQ may be lost when the bug occurs. However, this feature is very rarely used.<br />
* It makes controller reads take at least twice as long and does not guarantee a maximum runtime. Normally, it will take up to 4 passes.<br />
<br />
==== DPCM Safety using OAM DMA ====<br />
<br />
Because halts for DPCM fetches have very specific timing, it is possible to get glitch-free controller reads by timing all '''$4016''' and '''$4017''' reads to fall on one cycle parity. This is because the CPU alternates between two kinds of cycles: 'get' and 'put'. DPCM fetches normally occur only on put cycles, and because the first cycle after OAM DMA is normally guaranteed to be a get cycle, timed code can use OAM DMA to ensure the joypad reads land on get cycles.<br />
<ref>[http://forums.nesdev.org/viewtopic.php?p=171971 Forum post:] Rahsennor's OAM-synchronized controller read</ref> This is a relatively new technique and is not supported by several older emulators<ref>[http://forums.nesdev.org/viewtopic.php?f=2&t=14319&start=15#p172099 Forum post:] as of May 2016, Nintendulator and Nestopia do not accurately emulate OAM-synchronized controller reading.</ref>, but generally works in currently-supported emulators. In the following example code, the controller1 and controller2 labels must be in zeropage for the timing to work.<br />
<br />
This solution might be ideal, using fewer cycles than doing repeated reads, and taking a consistent amount of time. It can also be adapted for DPCM-conflict free reading of controllers that require a longer report, like [[four player adapters]] or the [[SNES mouse]] (see notes below).<br />
<br />
However, unlike the repeated reads solution, it can't be executed at any time. Instead it must be integrated into your NMI routine to coincide with your sprite OAM DMA once per frame.<br />
<br />
<pre><br />
lda #OAM<br />
sta $4014 ; ------ OAM DMA ------<br />
ldx #1 ; get put <- strobe code must take an odd number of cycles total<br />
stx buttons+0 ; get put get <- buttons must be in the zeropage<br />
stx $4016 ; put get put get<br />
dex ; put get<br />
stx $4016 ; put get put get<br />
loop:<br />
lda $4017 ; put get put GET <- loop code must take an even number of cycles total<br />
and #3 ; put get<br />
cmp #1 ; put get<br />
rol buttons+1, x ; put get put get put get (X = 0; waste 1 cycle for alignment)<br />
lda $4016 ; put get put GET<br />
and #3 ; put get<br />
cmp #1 ; put get<br />
rol buttons+0 ; put get put get put<br />
bcc loop ; get put [get] <- this branch must not be allowed to cross a page<br />
</pre><br />
<br />
Note that this example routine only reads two 8-bit controllers and does not take enough time to span more than one DPCM fetch. Routines longer than this must contend with two additional constraints:<br />
* When DMC DMA is delayed by an odd number of cycles, it takes 3 cycles instead of 4, changing the cycle parity. If extending this function to read more bits, care must be taken so that ''all'' CPU write cycles are aligned. Instructions with a single write cycle must align the write to avoid conflict with the DPCM fetch, and double-write instructions like ROL need to align both writes so that the DPCM fetch falls on the first write.<ref>[//forums.nesdev.org/viewtopic.php?p=231604#p231604 Forum post:] demonstration of how ROL instruction affects alignment for OAM DMA synchronized controller reading.</ref> If an interrupt can occur during the routine, it must be aligned so the fetch can only fall on the second of the three automatic stack writes.<br />
* When DMC DMA occurs near the end of OAM DMA, it steals an odd number of cycles, inverting the cycle parity. Every DMC period after that, a misaligned DPCM fetch will occur. Care must be taken to ensure this does not land on a joypad read. For longer functions, these misaligned cases can be resynced by landing the DPCM fetch on a single write cycle.<br />
<br />
See [[DMA]] for detailed information on DMA timing. However, game developers writing synced code may find it easier to consider just the specific case of DMC DMA used for reloading the sample buffer. These timings do not apply to the initial DMC DMA load caused by writing to $4015, and they are not sufficient for emulating DMA timings; emulator authors should refer to [[DMA]] for comprehensive information. A DMC DMA reload takes these cycle counts in these cases:<br />
* 4 cycles if it falls on a CPU read cycle<br />
* 3 cycles if it falls on an odd number of CPU write cycles<br />
* 4 cycles if it falls on an even number of CPU write cycles<br />
* An even number of cycles if it occurs during OAM DMA<br />
* An odd number of cycles if it occurs at the end of OAM DMA (changing cycle parity for the following code)<br />
<br />
This approach to DPCM safety has these benefits:<br />
* It can support any controller because it only does one pass and has no cycle budget.<br />
* It is nearly as fast as standard reads.<br />
* It avoids the bug and thus does not corrupt the sample byte or interfere with the APU's frame IRQ.<br />
It also has these drawbacks:<br />
* It uses timed code and relies on complicated DMA behavior, so it is harder to understand and modify.<br />
* Moving the code can break it by causing branches to cross a page boundary, changing the timing.<br />
* It must directly follow OAM DMA. Unusual features that skip OAM DMA on gameplay frames are not compatible with this approach. (On lag frames, normally both OAM DMA and controller reads are skipped. This is not a problem for synced reads.)<br />
* It does not work in older emulators that emulate the bug but have incorrect DMA timing (e.g. Nestopia). Modern emulators either don't emulate the bug or have correct-enough DMA timing.<br />
* Synced code that lasts longer than one DMC period minus 4 (usually 428 cycles) is difficult to write correctly. This is because write cycles must also be synced and specific desync cases occur if DMC DMA lands at the end of OAM DMA. However, this is the only approach that supports code of this length.<br />
<br />
== Other Useful Operations ==<br />
<br />
=== Button Flags ===<br />
<br />
It is helpful to define the buttons as a series of bit flags:<br />
<pre><br />
BUTTON_A = 1 << 7<br />
BUTTON_B = 1 << 6<br />
BUTTON_SELECT = 1 << 5<br />
BUTTON_START = 1 << 4<br />
BUTTON_UP = 1 << 3<br />
BUTTON_DOWN = 1 << 2<br />
BUTTON_LEFT = 1 << 1<br />
BUTTON_RIGHT = 1 << 0<br />
</pre><br />
<br />
And then buttons can be checked as follows:<br />
<pre><br />
lda buttons<br />
and #BUTTON_A | BUTTON_B<br />
beq notPressingAorB<br />
; Handle presses.<br />
notPressingAorB:<br />
</pre><br />
<br />
=== Calculating Presses and Releases ===<br />
<br />
To calculate newly pressed and newly released buttons by comparing against the last frame's buttons:<br />
<pre><br />
; newly pressed buttons: not held last frame, and held now<br />
lda last_frame_buttons, x<br />
eor #%11111111<br />
and buttons, x<br />
sta pressed_buttons, x<br />
<br />
; newly released buttons: not held now, and held last frame<br />
lda buttons, x<br />
eor #%11111111<br />
and last_frame_buttons, x<br />
sta released_buttons, x<br />
</pre><br />
<br />
=== Directional Safety ===<br />
<br />
Opposing directions (Up+Down and Left+Right) are possible on non-standard controllers, or even on a worn out standard one. Both directions can be tested for at the same time in an efficient bitwise operation:<br />
<pre><br />
lda buttons, x<br />
and #%00001010 ; Compare Up and Left...<br />
lsr a<br />
and buttons, x ; to Down and Right<br />
beq not_opposing<br />
; Use previous frame's directions<br />
lda buttons, x<br />
eor last_frame_buttons, x<br />
and #%11110000<br />
eor last_frame_buttons, x<br />
sta buttons, x<br />
not_opposing:<br />
</pre><br />
<br />
Diagonal directions can also be detected at the same time as opposing ones, by testing if more than 1 directional bit is set. This could be used as part of a 4-way joystick style control scheme:<br />
<pre><br />
lda buttons, x<br />
and #%00001111 ; If A & (A - 1) is nonzero, A has more than one bit set<br />
beq not_diagonal<br />
sec<br />
sbc #1<br />
and buttons, x<br />
beq not_diagonal<br />
; Use previous frame's directions<br />
lda buttons, x<br />
eor last_frame_buttons, x<br />
and #%11110000<br />
eor last_frame_buttons, x<br />
sta buttons, x<br />
not_diagonal:<br />
</pre><br />
<br />
As an example, the code above rejects the detected cases by using the direction bits from the previous frame, but depending on the situation another response might be more appropriate (e.g. cancel just the opposing bits, or clear all directions).<br />
<br />
== External Examples ==<br />
<br />
* [http://forums.nesdev.org/viewtopic.php?t=4124 Forum post:] Blargg's DMC-fortified controller read routine<br />
* [http://forums.nesdev.org/viewtopic.php?p=171971 Forum post:] Rahsennor's OAM-synchronized controller read<br />
* [http://forums.nesdev.org/viewtopic.php?f=2&t=14197 Forum post:] Drag's bitwise DMC-safe controller reading<br />
* [https://github.com/pinobatch/nrom-template/blob/master/src/pads.s pads.s:] pinobatch's NROM-template controller read routine<br />
<br />
== References ==<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=DMA&diff=21663DMA2024-03-15T15:03:33Z<p>Fiskbit: Adds more information to the summary table and rewords some points for clarity.</p>
<hr />
<div>The 2A03 contains a pair of DMA units, one for copying sprite data to PPU [[OAM]] and the other for copying DPCM sample data to the APU's [[APU DMC|DMC]] sample buffer. DMA is required for DPCM playback, and it is difficult to fill OAM without DMA. Unfortunately, DMC DMA can also result in data loss when reading registers with side effects, such as the joypads.<br />
<br />
==Summary==<br />
* The CPU alternates between cycles on which DMA can get (read) and cycles on which DMA can put (write). These are the first and second halves of APU cycles, respectively. At power-on, whether the first CPU cycle is get or put is random.<br />
* If DMA tries to get on a put cycle, it waits and tries again next cycle. This wait is called an alignment cycle.<br />
* DMA can only halt on CPU read cycles. On write cycles, the halt fails and the DMA unit tries again next CPU cycle, repeating until successful.<br />
* OAM DMA halts the CPU, performs an optional alignment cycle, and then gets and puts 256 times, taking 513 or 514 cycles. It attempts to halt on the first CPU cycle after the $4014 write.<br />
* DMC DMA halts the CPU, performs a dummy cycle and an optional alignment cycle, and then gets once, taking 3 or 4 cycles. <br />
* The first, "load" DMC DMA after the $4015 write attempts to halt on the get cycle during the 2nd following APU cycle. The other, "reload" DMC DMAs attempt to halt on a put cycle. Failed halts try again on the next CPU cycle, repeating until successful.<br />
* The DMC DMA get takes precedence over OAM DMA get, delaying it, but the DMA cycles otherwise overlap, reducing the total cycle cost. This delay can force OAM DMA to add an alignment cycle.<br />
* DMC DMA has [[#Bugs|bugs triggered by stopping the sample at specific times]].<br />
* DMC DMA can [[#Register conflicts|corrupt joypad and PPUDATA ($2007) reads and cause extraneous reads of $4015-4017]].<br />
<br />
==Cadence==<br />
The DMA units cannot just read or write on any cycle as they wish. Instead, they alternate between '''get''' cycles where they can read and '''put''' cycles where they can write. If they need to perform an action that is not permitted on the current cycle, they wait.<br />
<br />
Get and put cycles are aligned to the first and second halves of the APU clock, respectively (called apu_clk1 and apu_clk2 in Visual2A03). While these cycles are sometimes described as even and odd CPU cycles, this is not accurate because the CPU and APU randomly power into either of 2 alignments relative to each other. Therefore, get and put may occur on different CPU cycle parities across different power cycles.<br />
<br />
==Behavior==<br />
During the DMA process, the CPU is halted and the 2A03's address and data lines are used for data transfer. The process involves a combination of no-operation cycles and access cycles. No-operation cycles come in 3 equivalent types: the halt cycle, a DMC-only dummy cycle, and an optional alignment cycle.<br />
<br />
When DMA is scheduled, the associated DMA unit attempts to halt the CPU. The CPU only allows this on read cycles. If the CPU is writing, it ignores the halt and the DMA unit waits until the next cycle to try again, repeating until successful. Delays of up to 3 cycles are possible, with read-modify-write instructions having 2 consecutive writes and interrupts having 3. The halting process itself takes 1 CPU cycle, during which no useful work is done.<br />
<br />
Once the CPU is halted, the DMA unit may need to perform some amount of non-access setup, taking up to 2 cycles. The exact timing of when DMA is scheduled and what kind of setup it needs depends on the type of DMA.<br />
<br />
The CPU is halted using its internal RDY input. When RDY is deasserted, the 6502 core repeats the last read cycle indefinitely, making no forward progress nor handling interrupts. On 2A03 CPUs, these repeated reads are externally visible on any no-operation DMA cycle, causing data loss if reading a register with side effects. On 2A07 CPUs, it is suspected that a different address (perhaps the DMA address) is on the bus, instead, during all no-operation cycles. See [[#Register conflicts|Register conflicts]] for more information.<br />
<br />
When the DMA process completes, the CPU performs the read it attempted when halted.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - General behavior</div><br />
<div class="mw-collapsible-content"><br />
* DMA halts normally:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA halt is delayed by writes:<br />
CPU writes <- DMA attempts to halt<br />
CPU writes <- DMA attempts to halt<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) [DMA occurs]<br />
CPU reads from address A <- CPU resumes execution<br />
<br />
* DMA has a non-access cycle:<br />
(halted) CPU reads from address A <- DMA halt cycle<br />
(halted) CPU reads from address A <- DMA does not read or write<br />
(halted) DMA accesses address B<br />
CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===OAM DMA===<br />
-----<br />
OAM DMA copies 256 bytes from a CPU page to PPU OAM via the [[PPU_registers#OAMDATA|OAMDATA ($2004)]] register. It is triggered by writing the page number (the high byte of the address) to [[PPU_registers#OAMDMA|OAMDMA ($4014)]]. OAM DMA is scheduled to halt the CPU on the first cycle after the register write. In the common case, it performs a halt cycle, an optional alignment cycle, and 256 get/put pairs. <br />
<br />
The 256 get/put pairs copy forward from the start of the page. Because DMA can only read on get cycles, an alignment cycle performing no useful work may be required before being able to read. All together, OAM DMA on its own takes 513 or 514 cycles, depending on whether alignment is needed.<br />
<br />
OAM DMA will copy from the page most recently written to $4014. This means that read-modify-write instructions such as INC $4014, which are able to perform a second write before the CPU can be halted, will copy from the second page written, not the first.<br />
<br />
OAM DMA has a lower priority than DMC DMA. If a DMC DMA get occurs during OAM DMA, OAM DMA is briefly paused. (See [[#DMC DMA during OAM DMA|DMC DMA during OAM DMA]])<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* Alignment is not needed:<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Alignment is needed:<br />
(put) CPU writes to $4014<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from $xx00<br />
(halted) (put) DMA writes to $2004<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
(halted) (get) DMA reads from $xxFF<br />
(halted) (put) DMA writes to $2004 <- DMA completes<br />
(get) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
===DMC DMA===<br />
-----<br />
DMC DMA copies a single byte to the DMC unit's sample buffer. This occurs automatically after the DMC enable bit, bit 4, of the [[APU#Status_($4015)|sound channel enable register ($4015)]] is set to 1, which starts DPCM sample playback using the current DMC settings in [[APU_DMC#Overview|registers $4010-4013]]. DMC DMA is scheduled when all of DPCM playback is enabled, there are bytes left in the sample, and the sample buffer is empty (see [[APU_DMC#Memory_reader|Memory reader]] and [[APU_DMC#Output_unit|Output unit]]). In the common cases, DMC DMA performs a halt cycle, a dummy cycle, an optional alignment cycle, and a get.<br />
<br />
The exact timing depends on the type of DMC DMA. There are two types: load and reload. Load DMAs occur after $4015 D4 is set, but only if the sample buffer is empty. They are scheduled to halt the CPU on a get cycle during the 2nd APU cycle after the write (that is, the 3rd or 4th CPU cycle). Reload DMAs occur in response to the sample buffer being emptied. Unlike load DMAs, they are scheduled to halt the CPU on a put cycle.<br />
<br />
After the halt, DMC DMA always performs a dummy cycle where no work is done. If the next cycle is not a get cycle, then a cycle will be spent on alignment. Then the DMA read is performed.<br />
<br />
DMC DMA normally takes 3 or 4 cycles, depending on whether alignment is needed. Because load and reload DMAs schedule on different cycle types, load DMAs take 3 cycles and reload DMAs take 4 unless the halt is delayed by an odd number of cycles. However, bugs can cause additional cycles; see [[#Bugs|Bugs]] below.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA</div><br />
<div class="mw-collapsible-content"><br />
* Load DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Load DMA (delayed 1 cycle):<br />
(get) \ CPU writes to $4015 <- DMC enabled <br />
(put) / during this APU cycle <- DMC enabled<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA:<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 1 cycle):<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 2 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B <br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* Reload DMA (delayed 3 cycles):<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU writes <- DMA attempts to halt<br />
(put) CPU writes <- DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
====Bugs====<br />
DMC DMA suffers from two bugs<ref>[https://forums.nesdev.org/viewtopic.php?p=250170#p250170 Forum post:] Fiskbit's manual DMA test suite</ref><ref>[https://forums.nesdev.org/viewtopic.php?p=275734#p275734 Forum post:] Fiskbit's explicit and implicit stop tests</ref> related to sample playback stopping around the time [[APU_DMC#Output_unit|a DMC output cycle ends]], which is what empties the sample buffer and triggers a reload DMA. This can happen explicitly, where the sample is stopped by clearing $4015 D4, or implicitly, where a non-looping 1-byte sample is started while the sample buffer is empty shortly before a reload DMA would schedule. Implicit stops require this type of sample because the load DMA for the first byte when the sample buffer is empty is the only way to implicitly end the sample just before a reload DMA; longer samples will instead be ended by the reload DMA itself, as normal.<br />
<br />
When sample playback is stopped during the APU cycle before a reload DMA would schedule (that is, on the 2nd or 3rd CPU cycle before the halt attempt), the DMA starts, but is aborted after a single cycle. If the halt is delayed due to a write cycle, the aborted DMA doesn't occur at all. This aborted DMA schedules regardless of how playback was stopped, whether explicitly or implicitly. In the implicit case, the write to begin the sample will normally be the 4th APU cycle before the reload DMA would schedule (8th or 9th CPU cycle before).<br />
<br />
On RP2A03H and late RP2A03G CPUs, when playback is stopped implicitly on the same APU cycle that a reload DMA would schedule (that is, the 1st CPU cycle before the halt attempt), an unexpected reload DMA occurs from the same address. This extra byte goes into the sample buffer and is played after the first byte, as with any normal fetch. On RP2A03G CPUs, this bug was introduced sometime in 1990; earlier chips are unaffected.<br />
<br />
It is not known whether 2A07 CPUs are affected by these bugs. Some clone hardware is known to be affected, and behavior on affected clones may differ from official CPUs. For example, UA6527P-based clones feature both the aborted DMA and unexpected DMA bugs, but samples take 1 APU cycle longer to end than on official CPUs, so to trigger these bugs with implicit stops, the sample-ending byte must be fetched 1 APU cycle earlier.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA bugs</div><br />
<div class="mw-collapsible-content"><br />
* Explicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC disabled<br />
(put) / during this APU cycle <- DMC disabled<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(get) CPU reads from address A <- CPU resumes execution<br />
<br />
* Implicit-stop aborted DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(halted) (put) CPU reads from address C <- DMA halt cycle<br />
(get) CPU reads from address C <- CPU resumes execution<br />
<br />
* Implicit-stop unexpected DMA:<br />
(get) \ CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) / during this APU cycle <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
The implicit-stop aborted DMA can be prevented with carefully placed write cycles. This can be necessary for synchronized code, where the aborted DMA's odd number of cycles can invert cycle parity. The following code synchronizes to a put cycle and uses precise write cycles to prevent any aborted DMA that may occur:<br />
STx $4015 ; Initiate DMC DMA.<br />
STx zp ; Force load DMA to the 4th cycle.<br />
; (If on a UA6527P-based clone, place a NOP here.)<br />
STx zp ; Override the aborted DMA.<br />
; The first cycle of the next instruction is a put cycle.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - aborted DMA workaround</div><br />
<div class="mw-collapsible-content"><br />
* Implicit-stop aborted DMA bypass (write on get):<br />
(get) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(put) CPU reads<br />
(get) CPU reads<br />
(put) CPU writes<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
<br />
* Implicit-stop aborted DMA bypass (write on put):<br />
(put) CPU writes to $4015 <- DMC enabled w/ buffer empty<br />
(get) CPU reads<br />
(put) CPU reads<br />
(get) CPU writes <- DMA attempts to halt<br />
(halted) (put) CPU reads from address A <- DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMA dummy cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
(get) CPU reads<br />
(put) CPU writes <- DMA attempts to halt<br />
(get) CPU reads<br />
</div></div></div><br />
<br />
===DMC DMA during OAM DMA===<br />
DMC and OAM use independent DMA units that only interact when both attempt to access memory on the same cycle. When accesses collide, DMC DMA is allowed to run and OAM DMA is paused, trying again on the next cycle. This can cause OAM DMA to have to perform an additional alignment cycle before continuing. No-operation cycles are allowed to overlap with each other and with access cycles, allowing cycles to be saved.<br />
<br />
In the common case, DMC DMA occurring during OAM DMA will cost only 2 cycles: 1 cycle for the DMC DMA get and then 1 cycle for OAM DMA to align back to a get. However, if DMC DMA occurs at the end of OAM DMA, it can take 1 or 3 cycles. If it schedules for the second-to-last put, its get will occur on the first cycle after OAM DMA, taking just 1 cycle total. If it schedules for the last put, it will instead extend 3 cycles beyond the end of OAM DMA.<br />
<br />
OAM DMA is sometimes used to synchronize code to avoid conflicts with DMC DMA when reading hardware registers, but because DMC DMA takes an odd number of cycles if it lands at the end, synchronization is not guaranteed.<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - DMC DMA during OAM DMA</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA at the start of OAM DMA (write on get), taking 2 cycles<br />
(get) CPU writes to $4014<br />
(halted) (put) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xx00 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) DMA reads from $xx01<br />
(halted) (put) DMA writes to $2004<br />
...<br />
<br />
* DMC DMA at the start of OAM DMA (write on put), taking 2 cycles<br />
(put) CPU writes to $4014 <- DMC DMA attempts to halt<br />
(halted) (get) CPU reads from address A <- DMC and OAM DMA halt cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA dummy cycle, OAM DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from $xx00<br />
(halted) (put) OAM DMA writes to $2004<br />
...<br />
<br />
* DMC DMA in the middle of OAM DMA, taking 2 cycles<br />
...<br />
(halted) (get) OAM DMA reads from address C<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from address C+1 <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(halted) (put) CPU reads from address A <- OAM DMA alignment cycle<br />
(halted) (get) OAM DMA reads from address C+2<br />
...<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 1 cycle<br />
...<br />
(halted) (get) OAM DMA reads from $xxFE<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) OAM DMA reads from $xxFF <- DMC DMA dummy cycle<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
<br />
* DMC DMA on second-to-last OAM DMA put, taking 3 cycles<br />
...<br />
(halted) (get) OAM DMA reads from $xxFF<br />
(halted) (put) OAM DMA writes to $2004 <- DMC DMA halt cycle<br />
(halted) (get) CPU reads from address A <- DMC DMA dummy cycle<br />
(halted) (put) CPU reads from address A <- DMC DMA alignment cycle<br />
(halted) (get) DMC DMA reads from address B<br />
(put) CPU reads from address A <- CPU resumes execution<br />
</div></div></div><br />
<br />
==Register conflicts==<br />
On the 2A03, while the CPU is halted, it repeats the read cycle on which it was halted during every no-operation DMA cycle (that is, when the DMA units are not reading or writing). If the CPU was reading a register with side-effects, this can cause data to be lost. While this isn't realistically a problem with OAM DMA because of its particular timing constraints, it is a very real problem with DMC DMA that must usually be worked around. Example registers include PPUSTATUS ($2002), PPUDATA ($2007), and sound status ($4015). When conflicting with DMC DMA, these will see 2 or more extra reads. (Note that $2007 reads on adjacent cycles may have unexpected behavior.)<br />
<br />
Most frequently, these DMC DMA conflicts occur with joypad reads, though the mechanism is slightly different. Joypads are clocked via direct lines from the CPU, called joypad 1 /OE and joypad 2 /OE, rather than going over the address bus. These output enables remain asserted the entire CPU cycle and even across adjacent cycles if they're both reading the same joypad register. Therefore, controllers only see a single read for each contiguous set of reads of a joypad register.<br />
<br />
The console type affects joypad extra-read behavior. On the RF Famicom, additional hardware outside the 2A03 only passes joypad 1 /OE and joypad 2 /OE through during one half of the clock cycle, meaning the joypad sees a clock on every single CPU read cycle rather than just every contiguous set<ref>[https://forums.nesdev.org/viewtopic.php?p=275946#p275946 Forum post:] lidnariq's RF Famicom joypad clocking explanation</ref>. The RF Famicom is the only console known to behave this way. The AV Famicom and NES-001 are confirmed to use the per-contiguous-set behavior.<ref>[https://forums.nesdev.org/viewtopic.php?p=275468#p275468 Forum post:] Fiskbit's joypad read cycle breakdown</ref><br />
<br />
This is further complicated by esoteric behavior regarding how 2A03 registers are activated: instead of checking the full 2A03 address bus, it checks bits 4-0 from the 2A03 address bus and bits 15-5 from the 6502 core. The 6502 core keeps the same address while halted, so if it was reading from $4000-401F, the DMA address can unintentionally activate 2A03 registers. This can lead to bus conflicts and an extra read from the other joypad, and can even prevent an extra read of the current joypad.<ref>[https://forums.nesdev.org/viewtopic.php?p=275132#p275132 Forum post:] Fiskbit's APU register activation test</ref><br />
<br />
The 2A07 fixes these extra read problems, but the mechanism is not yet understood. Experimentally, the CPU still performs a read on the halting cycle; if OAM DMA is done from the $4000 page, the open bus value used by the OAM DMA is the opcode of the instruction following the $4014 write. This means that 6502 core reads still occur when halted, at least on the first cycle. Like on NTSC, this DMA also does not trigger 2A07 registers if the 6502 core is not reading from $4000-401F. Unlike NTSC, reading a joypad register when DMA reads an address that matches the other joypad register in its low 5 bits does not clock the other joypad.<br />
<br />
Workarounds exist for this issue. Most commonly, [[Controller_reading_code#DPCM_Safety_using_Repeated_Reads|joypads are read multiple times]] until the same result is seen twice in row, reducing or eliminating the chance of accepting corrupted data. However, any collisions during this time may corrupt the DPCM data, and this strategy is not suitable for all affected registers. Alternatively, [[Controller_reading_code#DPCM_Safety_using_OAM_DMA|reads synchronized using OAM DMA]] can ensure a collision never happens, but this enforces strict timing constraints on the code and has numerous caveats, particularly for functions longer than one DMC output cycle (sample byte period).<br />
<br />
<div style="margin-left: 2em;"><br />
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding: 5px; display: inline-block; min-width: 25em; overflow:auto;"><br />
<div style="font-weight:bold;line-height:1.6;">Examples - Register conflicts</div><br />
<div class="mw-collapsible-content"><br />
* DMC DMA collides with $2007 read (3 extra reads)<br />
(halted) (put) CPU reads from $2007 <- DMA halt cycle<br />
(halted) (get) CPU reads from $2007 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $2007 <- DMA alignment cycle<br />
(halted) (get) DMA reads from address B<br />
(put) CPU reads from $2007 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 ($4016) read (1 or 3 extra reads)<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C000<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (0 or 4 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4016.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C016 and $4016<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
* DMC DMA collides with JOYPAD1 read (1 extra read of JOYPAD2, 1 or 3 extra of JOYPAD1)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4017.<br />
** This triggers a bus conflict, corrupting the DMA read.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C017 and $4017<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
<br />
*DMC DMA collides with JOYPAD1 read (1 or 3 extra reads)<br />
** The combined address from 6502 core bits 15-5 and 2A03 bits 4-0 is $4015.<br />
** This causes the 2A03 to read $4015 and ignore the DMA value on the external data bus.<br />
(halted) (put) CPU reads from $4016 <- DMA halt cycle<br />
(halted) (get) CPU reads from $4016 <- DMA dummy cycle<br />
(halted) (put) CPU reads from $4016 <- DMA alignment cycle<br />
(halted) (get) DMA reads from $C015, 2A03 reads from $4015 internally<br />
(put) CPU reads from $4016 <- CPU resumes execution<br />
</div></div></div><br />
<br />
==References==<br />
:* [https://github.com/emu-russia/breaks/blob/master/BreakingNESWiki_DeepL/APU/dma.md BreakingNESWiki:] DMA circuit analysis<br />
:* [https://forums.nesdev.org/viewtopic.php?t=14120 Forum post:] Disch's OAM/DMC DMA test results<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=NES_2.0&diff=21656NES 2.02024-03-08T16:23:46Z<p>Fiskbit: /* Default Expansion Device */ Adds Famicom Network Controller link. Updates SNES mouse link to dedicated SNES mouse page.</p>
<hr />
<div>'''NES 2.0''' extends the [[iNES]] single file cart format to better describe NES/Famicom-compatible cartridge hardware. Some of its purpose include:<br />
* Removing the need to use ROM checksums, or other information outside the header, to disambiguate emulation behavior not encoded by iNES.<br />
* Making room for new mapper allocation.<br />
* Allowing for larger ROM sizes.<br />
* Supporting other than standard NES/Famicom console types such as the Nintendo Vs. System and enhanced Famiclones.<br />
* Providing additional information such as the region-specific CPU/PPU type and default expansion port devices.<br />
* Replaces the deprecated [[UNIF]] format.<br />
<br />
The format is [[#Backwards Compatibility to iNES|backwards-compatible]] to iNES, so that ROM images with a NES 2.0 header run in non-NES-2.0-compliant emulators as long as they do not require NES-2.0-exclusive features.<br />
<br />
=Identification=<br />
A file is a NES 2.0 ROM image file if it begins with "NES<EOF>" (same as iNES) and, additionally, the byte at offset 7 has bit 2 clear and bit 3 set:<br />
bool iNESFormat=false;<br />
if (header[0]=='N' && header[1]=='E' && header[2]=='S' && header[3]==0x1A)<br />
iNESFormat=true;<br />
<br />
bool NES20Format=false;<br />
if (iNESFormat==true && (header[7]&0x0C)==0x08)<br />
NES20Format=true;<br />
=File Structure=<br />
A NES 2.0 file contains a sixteen-byte header, followed by Trainer, PRG-ROM, CHR-ROM and Miscellaneous ROM data.<br />
<br />
==Header==<br />
Offset Meaning<br />
--------------<br />
0-3 Identification String. Must be "NES<EOF>".<br />
<br />
4 [[#PRG-ROM Area|PRG-ROM]] size LSB<br />
5 [[#CHR-ROM Area|CHR-ROM]] size LSB<br />
<br />
6 Flags 6<br />
D~7654 3210<br />
---------<br />
NNNN FTBM<br />
|||| |||+-- [[#Nametable layout|Hard-wired nametable layout]]<br />
|||| ||| 0: Vertical arrangement ("mirrored horizontally") or mapper-controlled<br />
|||| ||| 1: Horizontal arrangement ("mirrored vertically")<br />
|||| ||+--- "Battery" and other non-volatile memory<br />
|||| || 0: Not present<br />
|||| || 1: Present<br />
|||| |+--- 512-byte [[#Trainer Area|Trainer]]<br />
|||| | 0: Not present<br />
|||| | 1: Present between Header and PRG-ROM data<br />
|||| +---- [[#Nametable layout|Alternative nametables]]<br />
|||| 0: No<br />
|||| 1: Yes<br />
++++------ Mapper Number D3..D0<br />
<br />
7 Flags 7<br />
D~7654 3210<br />
---------<br />
NNNN 10TT<br />
|||| ||++- Console type<br />
|||| || 0: Nintendo Entertainment System/Family Computer<br />
|||| || 1: Nintendo [[Vs. System]]<br />
|||| || 2: Nintendo [[PC10 ROM-Images|Playchoice 10]]<br />
|||| || 3: [[#Extended Console Type|Extended Console Type]]<br />
|||| ++--- NES 2.0 identifier<br />
++++------ Mapper Number D7..D4<br />
<br />
8 [[Mapper]] MSB/[[Submapper]]<br />
D~7654 3210<br />
---------<br />
SSSS NNNN<br />
|||| ++++- Mapper number D11..D8<br />
++++------ Submapper number<br />
<br />
9 [[#PRG-ROM Area|PRG-ROM]]/[[#CHR-ROM Area|CHR-ROM]] size MSB<br />
D~7654 3210<br />
---------<br />
CCCC PPPP<br />
|||| ++++- PRG-ROM size MSB<br />
++++------ CHR-ROM size MSB<br />
<br />
10 [[#PRG-(NV)RAM/EEPROM|PRG-RAM/EEPROM]] size<br />
D~7654 3210<br />
---------<br />
pppp PPPP<br />
|||| ++++- PRG-RAM (volatile) shift count<br />
++++------ PRG-NVRAM/EEPROM (non-volatile) shift count<br />
If the shift count is zero, there is no PRG-(NV)RAM.<br />
If the shift count is non-zero, the actual size is<br />
"64 << shift count" bytes, i.e. 8192 bytes for a shift count of 7.<br />
<br />
11 [[#CHR-(NV)RAM|CHR-RAM]] size<br />
D~7654 3210<br />
---------<br />
cccc CCCC<br />
|||| ++++- CHR-RAM size (volatile) shift count<br />
++++------ [[:Category:Mappers with battery-backed CHR-RAM|CHR-NVRAM]] size (non-volatile) shift count<br />
If the shift count is zero, there is no CHR-(NV)RAM.<br />
If the shift count is non-zero, the actual size is<br />
"64 << shift count" bytes, i.e. 8192 bytes for a shift count of 7.<br />
<br />
12 [[#CPU/PPU Timing|CPU/PPU Timing]]<br />
D~7654 3210<br />
---------<br />
.... ..VV<br />
++- CPU/PPU timing mode<br />
0: RP2C02 ("NTSC NES")<br />
1: RP2C07 ("Licensed PAL NES")<br />
2: Multiple-region<br />
3: UA6538 ("Dendy")<br />
<br />
13 When Byte 7 AND 3 =1: [[#Vs. System Type|Vs. System Type]]<br />
D~7654 3210<br />
---------<br />
MMMM PPPP<br />
|||| ++++- Vs. PPU Type<br />
++++------ Vs. Hardware Type<br />
<br />
When Byte 7 AND 3 =3: [[#Extended Console Type|Extended Console Type]]<br />
D~7654 3210<br />
---------<br />
.... CCCC<br />
++++- Extended Console Type<br />
<br />
14 [[#Miscellaneous ROM Area|Miscellaneous ROMs]]<br />
D~7654 3210<br />
---------<br />
.... ..RR<br />
++- Number of miscellaneous ROMs present<br />
<br />
15 [[#Default Expansion Device|Default Expansion Device]]<br />
D~7654 3210<br />
---------<br />
..DD DDDD<br />
++-++++- Default Expansion Device<br />
<br />
==Trainer Area==<br />
The Trainer Area follows the 16-byte Header and precedes the PRG-ROM area if bit 2 of Header byte 6 is set. It is always 512 bytes in size if present,<br />
and contains data to be loaded into CPU memory at $7000. It is only used by some games that were modified to run on different hardware from the original cartridges,<br />
such as early RAM cartridges and emulators, and which put some additional compatibility code into those address ranges.<br />
==PRG-ROM Area==<br />
The PRG-ROM Area follows the 16-byte Header and the Trainer Area and precedes the CHR-ROM Area. Header byte 4 (LSB) and bits 0-3 of Header byte 9 (MSB) together specify its size.<br />
If the MSB nibble is $0-E, LSB and MSB together simply specify the PRG-ROM size in 16 KiB units:<br />
++++----------- Header byte 9 D3..D0<br />
|||| ++++-++++- Header byte 4<br />
D~BA98 7654 3210<br />
--------------<br />
BBBB BBBB BBBB<br />
++++-++++-++++- PRG-ROM size in 16 KiB units,<br />
values $000-$EFF for 0..62,898,176 bytes<br />
If the MSB nibble is $F, an exponent-multiplier notation is used:<br />
++++----------- Header byte 9 D3..D0<br />
|||| ++++-++++- Header byte 4<br />
D~BA98 7654 3210<br />
--------------<br />
1111 EEEE EEMM<br />
|||| ||++- Multiplier, actual value is MM*2+1 (1,3,5,7)<br />
++++-++--- Exponent (2^E), 0-63<br />
<br />
The actual PRG-ROM size is 2^E *(MM*2+1) bytes.<br />
The exponent-multiplier form may only be used if the PRG-ROM size cannot be specified correctly using the simpler notation. If the PRG-ROM data has an odd size that cannot<br />
be represented in either notation, the data must be padded to a size that can be represented.<br />
<br />
In Vs. Dual System ROM images, the first half block of the specified PRG-ROM size belongs to the first unit, and the second half block of PRG-ROM belongs to the the second unit.<br />
24 KiB (half-)blocks are mapped to $A000-$FFFF both in Vs. Unisystem and Vs. Dual System.<br />
An exception is granted for two oddly-sized Vs. System ROM images with a total of 40 KiB PRG-ROM, which are defined to represent 32 KiB +8 KiB instead:<br />
* ''Vs. Gumshoe'', [[#Vs. System Type|Vs. Hardware type]] #0:<br />
** First 32 KiB represent the entire CPU $8000-$FFFF area, including the CPU $8000-$9FFF area with $4016 D2=0;<br />
** Second 8 KiB represent the CPU $8000-$9FFF area with $4016 D2=1.<br />
* ''Vs. Raid on Bungeling Bay'', [[#Vs. System Type|Vs. Hardware type]] #6:<br />
** First 32 KiB represent the first unit's PRG-ROM at CPU $8000-$FFFF;<br />
** Second 8 KiB represent the second unit's PRG-ROM at CPU $E000-$FFFF.<br />
** The second unit only executes a dummy program that does nothing except set a flag in the shared WRAM at $6000-$67FF.<br />
<br />
==CHR-ROM Area==<br />
The CHR-ROM Area, if present, follows the Trainer and PRG-ROM Areas and precedes the Miscellaneous ROM Area. Header byte 5 (LSB) and bits 4-7 of Header byte 9 (MSB)<br />
specify its size. If the MSB nibble is $0-E, LSB and MSB together simply specify the CHR-ROM size in 8 KiB units:<br />
++++----------- Header byte 9 D7..D4<br />
|||| ++++-++++- Header byte 5<br />
D~BA98 7654 3210<br />
--------------<br />
BBBB BBBB BBBB<br />
++++-++++-++++- CHR-ROM size in 8 KiB units,<br />
values $000-$EFF for 0..31,449,088 bytes<br />
If the MSB nibble is $F, an exponent-multiplier notation is used:<br />
++++----------- Header byte 9 D7..D4<br />
|||| ++++-++++- Header byte 5<br />
D~BA98 7654 3210<br />
--------------<br />
1111 EEEE EEMM<br />
|||| ||++- Multiplier, actual value is MM*2+1 (1,3,5,7)<br />
++++-++--- Exponent (2^E), 0-63<br />
<br />
The actual CHR-ROM size therefore becomes 2^E * (MM*2+1).<br />
The exponent-multiplier form may only be used if the CHR-ROM size cannot be specified correctly using the simpler notation. If the CHR-ROM data has an odd size that cannot<br />
be represented by either notation, the data must be padded to a size that can be represented.<br />
<br />
For Vs. Dual System ROM images, if the CHR-ROM size is 32 KiB, the first 16 KiB belong to the first unit, and the second 16 KiB of CHR-ROM belong to the second unit.<br />
If the CHR-ROM size is 16 KiB, the both units use the same bank-switched 16 KiB CHR-ROM data.<br />
<br />
==Miscellaneous ROM Area==<br />
The Miscellaneous ROM Area, if present, follows the CHR-ROM area and occupies the remainder of the file. Its size is not explicitly denoted in the header, and can be deduced<br />
by subtracting the 16-byte Header, Trainer, PRG-ROM and CHR-ROM Area sizes from the total file size. The meaning of this data depends on the console type and mapper type; Header<br />
byte 14 is used to denote the presence of the Miscellaneous ROM Area and the number of ROM chips in case any disambiguation is needed. Currently, miscellaneous ROMs are defined<br />
for the following situations:<br />
* on console type [[PC10 ROM-Images|Playchoice 10]], an 8 KiB INST ROM, 16 bytes of PROM Data, 16 bytes of PROM Counter Out data, for a total of "3" miscellaneous ROMs;<br />
* on console type [[VT369]], 4 KiB of ROM that is embedded into the NES-on-a-chip itself;<br />
* on [[INES Mapper 086]] submapper 1, a single miscellaneous ROM containing speech data;<br />
* on [[NES 2.0 Mapper 355]], the embedded ROM of the PIC16C54 microcontroller that the games use for protection purposes.<br />
* on [[NES 2.0 Mapper 561]] and [[NES 2.0 Mapper 562]] to deliver trainers that do not match the iNES trainer conventions in size (512 byte) or location ($7000).<br />
<br />
=Notes=<br />
==Backwards Compatibility to iNES==<br />
* Bytes 0-7 have the same meaning as in [[iNES]], so that NES-2.0-headered games will still run in emulators that do not support NES 2.0 unless the header specifies features that those older emulators did not support anyway.<br />
* The NES 2.0 identifier (Byte 7 D3..D2) has been chosen so that it does not collide with any valid iNES header nor with any known ROM image that has garbage in bytes 7-15 such as "DiskDude!".<br />
==Nametable layout==<br />
Byte 6 (Flags 6) contains two bits to describe the [[Mirroring#Nametable Mirroring|nametable layout]] of the cartridge.<br />
<br />
D~7654 3210<br />
---------<br />
.... F..M<br />
| +-- Horizontal/vertical hard-wired mirroring.<br />
+----- All other nametable layout variations<br />
<br />
* Bit 0 is normally relevant only if the mapper does not allow the mirroring type to be switched. It should be set to zero otherwise.<br />
* For some mappers, bit 3 means that 4 KiB of RAM are present at PPU $2000-2FFF, exclusive to that region, and cannot be banked, replaced, or rearranged. This applies to:<br />
** [[INES Mapper 004|Mapper 4]] (MMC3)<br />
** [[INES Mapper 206|Mapper 206]] (DxROM, etc. MMC3-like subset)<br />
** [[NES 2.0 Mapper 262|Mapper 262]] (Street Heroes)<br />
* Several mappers use bit 3 to mean something different:<br />
** [[INES Mapper 030#Nametable Configuration|Mapper 30]] (UNROM 512) - This board can be wired for H/V fixed, 1-screen, or 4-screen.<br />
** [[INES Mapper 218|Mapper 218]] (Magic Floor) - This experimental board has 4 configurations that allow the internal 2k CIRAM to be used for both CHR and nametables at once.<br />
<br />
==PRG-(NV)RAM/EEPROM==<br />
The PRG-(NV)RAM/EEPROM fields specify the sizes of...<br />
* Memory that is mapped into CPU address space, regardless of whether that memory is internal to a mapper chip or in a separate RAM chip;<br />
* EEPROM even if it is not mapped into CPU address space.<br />
They do not specify the sizes of...<br />
* Mapper-chip-internal memory that is not mapped into CPU address space, even if battery-backed, such as the [[Namco 163]]'s wavetable RAM which some games use to store saved game data. The size of such memory is part of the Mapper definition instead. The Battery bit (Header byte 6 bit 1) denotes whether such memory is battery-backed. The [[MMC5]]'s EXRAM is not included in the PRG-RAM size, as it can be mapped by software to CPU, PPU, or no address space at all;<br />
* self-flashable PRG-ROM;<br />
* external storage such as cassette tape or the ASCII Turbo File.<br />
When the upper nibble (PRG-NVRAM/EEPROM) has a non-zero value, the Battery bit (Header byte 6 bit 1) must always be set for compatibility with [[iNES]]. Conversely, if the Battery bit is set, the upper nibble must have a non-zero value, unless the only battery-backed memory is either mapper-chip-internal memory that is not mapped into CPU address space, such as the [[Namco 163]]'s wavetable RAM, or the PRG-ROM is self-flashable.<br />
<br />
==CHR-(NV)RAM==<br />
* In the presence of a NES 2.0 Header, an emulator must not assume that if a ROM image specifies no CHR-ROM, the game will automatically have 8 KiB of CHR-RAM; all CHR-RAM must instead be explicitly specified in Header byte 11.<br />
* Memory that is permanently mapped into the nametable address space (PPU $2000-$2FFF) is not included in the CHR-RAM size. Setting the hard-wired four-screen mode bit in Header byte 6 bit 3 therefore does not entail a 4 KiB increase of the CHR-RAM size.<br />
* The [[MMC5]]'s EXRAM is not included in the CHR-RAM size, as it can be mapped by software to CPU, PPU, or no address space at all.<br />
<br />
==CPU/PPU Timing==<br />
For non-homebrew NES/Famicom games, this field's value is always a function of the region in which a game was released:<br />
Value Meaning Regions<br />
0 RP2C02 North America, Japan, South Korea, Taiwan<br />
1 RP2C07 Western Europe, Australia<br />
2 Multiple Multiple<br />
3 UA6538 Eastern Europe, Russia, Mainland China, India, Africa<br />
Value 2 ("multiple-region") is used either if a game was released with identical ROM content in both NTSC and PAL countries, such as Nintendo's early games, or if the game detects the console's timing and adjusts itself. Emulators should implement this value by either switching to a user-specified "Default Region" or by keeping the previously-set region.<br />
<br />
[[VTxx|V.R. Technology Famiclones]] only come with RP2C02 or UA6538 timing, so games with such a console type can only bear values 0 or 3.<br />
<br />
==Vs. System Type==<br />
When the console type in Header byte 7 D1..D0 is 1 (Vs. System), the lower nibble of Header byte 13 specifies the Vs. PPU type, and the upper nibble the non-PPU-based protection<br />
type and whether the ROM is for the Vs. Unisystem or the Vs. Dual System.<br />
Vs. PPU types (Header byte 13 D3..D0):<br />
$0: RP2C03B<br />
$1: RP2C03G<br />
$2: RP2C04-0001<br />
$3: RP2C04-0002<br />
$4: RP2C04-0003<br />
$5: RP2C04-0004<br />
$6: RC2C03B<br />
$7: RC2C03C<br />
$8: RC2C05-01 ($2002 AND $?? =$1B)<br />
$9: RC2C05-02 ($2002 AND $3F =$3D)<br />
$A: RC2C05-03 ($2002 AND $1F =$1C)<br />
$B: RC2C05-04 ($2002 AND $1F =$1B)<br />
$C: RC2C05-05 ($2002 AND $1F =unknown)<br />
$D-F: reserved<br />
For copy protection purposes, these PPU types have different [[PPU palettes|palettes]]; the RC2C05 PPUs furthermore swap [[PPU registers]] $2000 and $2001 and return a signature in the lower bits of $2002. If a game uses the DIP switches to select different PPU models, this field represents the correct PPU model when those DIP switches are all set to zero.<br />
Vs. Hardware type (Header byte 13 D7..D4):<br />
$0: Vs. Unisystem (normal)<br />
$1: Vs. Unisystem (RBI Baseball protection)<br />
$2: Vs. Unisystem (TKO Boxing protection)<br />
$3: Vs. Unisystem (Super Xevious protection)<br />
$4: Vs. Unisystem (Vs. Ice Climber Japan protection)<br />
$5: Vs. Dual System (normal)<br />
$6: Vs. Dual System (Raid on Bungeling Bay protection)<br />
Refer to the [[Vs. System]] entry for more information.<br />
==Extended Console Type==<br />
When the console type in Header byte 7 D1..D0 is 3 (Extended), the lower nibble of Header byte 13 specifies the type of console on which the ROM image is supposed to be run.<br />
$0 [Regular NES/Famicom/Dendy]<br />
$1 [Nintendo Vs. System]<br />
$2 [Playchoice 10]<br />
$3 Regular Famiclone, but with CPU that supports Decimal Mode<br />
$4 Regular NES/Famicom with [[EPSM]] module or plug-through cartridge<br />
$5 [[VT01 STN_Palette|V.R. Technology VT01 with red/cyan STN palette]]<br />
$6 [[VTxx|V.R. Technology VT02]]<br />
$7 [[VTxx|V.R. Technology VT03]]<br />
$8 [[VTxx|V.R. Technology VT09]]<br />
$9 V.R. Technology VT32<br />
$A V.R. Technology VT369<br />
$B UMC UM6578<br />
$C [[Famicom Network System]]<br />
$D-$F reserved<br />
Values $0-$2 are not used for the extended console type, as they can be expressed by only using Header byte 7 D1..D0. They are reserved here so that emulators<br />
can fold the information in Header Byte 7 D1..D0 and Header byte 13 into one "console type" variable without recoding the values.<br />
<br />
==Default Expansion Device==<br />
Header byte 15 indicates that the ROM expects a specific set of devices accessible at CPU $4016/$4017. For an emulator that wishes to automatically provide selection of needed peripherals, this gives the required information directly within the header.<br />
<br />
Value $00 is reserved for compatibility with older versions of this specification and indicates no information on the default input device.<br />
<br />
In almost all cases, this byte will specify ''the'' device without which the game cannot be played at all, such as the NES Zapper or Power Pad. If a game supports an ''optional'' expansion port device, and having that device connected does not preclude using the normal controllers with that game, this byte will specify that device, such as the ASCII Turbo File or the Arkanoid Vaus Controller. For games that support multiple combinations of expansion devices, this byte will denote the game's default selection.<br />
<br />
This byte does not denote devices that connect to a cartridge; such devices are part of the respective Mapper's definition.<br />
$00 Unspecified<br />
$01 [[Standard controller|Standard NES/Famicom controllers]]<br />
$02 NES [[Four Score]]/Satellite with two additional standard controllers<br />
$03 Famicom Four Players Adapter with two additional standard controllers using the [[Four player adapters#"Simple" Famicom adapters|"simple"]] protocol<br />
$04 [[Vs. System]] (1P via $4016)<br />
$05 Vs. System (1P via $4017)<br />
$06 Reserved<br />
$07 Vs. [[Zapper]]<br />
$08 [[Zapper]] ($4017)<br />
$09 Two Zappers<br />
$0A Bandai Hyper Shot Lightgun<br />
$0B [[Power Pad]] Side A<br />
$0C [[Power Pad]] Side B<br />
$0D [[Power Pad#Family Trainer Mat|Family Trainer]] Side A<br />
$0E [[Power Pad#Family Trainer Mat|Family Trainer]] Side B<br />
$0F [[Arkanoid controller|Arkanoid Vaus Controller (NES)]]<br />
$10 [[Arkanoid controller|Arkanoid Vaus Controller (Famicom)]]<br />
$11 Two Vaus Controllers plus [[Family BASIC Data Recorder|Famicom Data Recorder]]<br />
$12 [[Konami Hyper Shot]] Controller<br />
$13 [[Coconuts Pachinko]] Controller<br />
$14 [[Exciting Boxing Punching Bag]] (Blowup Doll)<br />
$15 [[Jissen Mahjong controller|Jissen Mahjong Controller]]<br />
$16 [[Partytap|Party Tap]] <br />
$17 [[Oeka Kids tablet|Oeka Kids Tablet]]<br />
$18 Sunsoft Barcode Battler<br />
$19 [[Miracle_Piano|Miracle Piano Keyboard]]<br />
$1A Pokkun Moguraa (Whack-a-Mole Mat and Mallet)<br />
$1B Top Rider (Inflatable Bicycle)<br />
$1C Double-Fisted (Requires or allows use of two controllers by one player)<br />
$1D [[Famicom 3D glasses|Famicom 3D System]]<br />
$1E Doremikko Keyboard<br />
$1F R.O.B. Gyro Set<br />
$20 [[Family BASIC Data Recorder|Famicom Data Recorder]] ("silent" keyboard)<br />
$21 ASCII Turbo File<br />
$22 IGS Storage Battle Box<br />
$23 [[Family BASIC Keyboard]] plus Famicom Data Recorder<br />
$24 Dongda PEC-586 Keyboard<br />
$25 Bit Corp. Bit-79 Keyboard<br />
$26 Subor Keyboard<br />
$27 Subor Keyboard plus [[Mouse#Subor Mouse|mouse]] (3x8-bit protocol)<br />
$28 Subor Keyboard plus mouse (24-bit protocol via $4016)<br />
$29 [[Super NES Mouse|SNES Mouse]] ($4017.d0)<br />
$2A Multicart<br />
$2B Two [[SNES_controller|SNES controllers]] replacing the two standard NES controllers<br />
$2C RacerMate Bicycle<br />
$2D U-Force<br />
$2E R.O.B. Stack-Up<br />
$2F City Patrolman Lightgun<br />
$30 Sharp C1 Cassette Interface<br />
$31 Standard Controller with swapped Left-Right/Up-Down/B-A<br />
$32 Excalibur Sudoku Pad<br />
$33 ABL Pinball<br />
$34 Golden Nugget Casino extra buttons<br />
$35 Unknown famiclone keyboard used by the "Golden Key" educational cartridge<br />
$36 Subor Keyboard plus mouse (24-bit protocol via $4017)<br />
$37 [[Port test controller]]<br />
$38 Bandai Multi Game Player Gamepad buttons<br />
$39 Venom TV Dance Mat<br />
$3A LG TV Remote Control<br />
$3B [[Famicom Network Controller]]<br />
$3C King Fishing Controller<br />
Notes:<br />
* The Famicom Four Players Adapter ($03) is denoted only if the additional controllers provide ''independent'' 3P/4P input, not if they just alias the built-in 1P/2P controllers.<br />
* So far, there have been no games that provide independent 3P/4P input solely through the [[Four player adapters#Hori 4 Players Adapter|"Hori"]] protocol, which is why there has been no value assigned for it yet.<br />
* For Vs. System games that do not care which stick is used and therefore could be denoted either with value $04 or $05, use value $04.<br />
* Value $06 originally denoted "Pinball (Japan)" and was thought to represent a unique wiring variant, but was since found to represent a peculiar MAME behavior that MAME has since removed.<br />
* "Two Vaus Controllers plus Famicom Data Recorder" ($11) can be trivially emulated as just connecting a Famicom Vaus controller, or sophisticatedly emulated as "Connect two daisy-chained Vaus controllers on startup, disconnect them and connect Family BASIC keyboard with Data Recorder when the user selects Tape Playback or Tape Record from the emulator's user interface; detach these and re-connect the two Vaus controllers when the user selects Tape Stop".<br />
* "Double-Fisted" ($1C) assumes a Four Score is connected, which allows two players to use two controllers at once (Smash T.V.) if the game supports two players.<br />
* The difference between "Famicom Data Recorder" ($20) and "Family BASIC Keyboard" ($23) is that although $20 emulates the Family BASIC keyboard's response to strobe, no actual emulated keyboard input is registered ("silent" keyboard), allowing desktop emulators to keep allowing the use of the host's keyboard for other purposes (such as D-Pad input), and not necessitating the display of an on-screen keyboard on mobile emulators.<br />
* "Multicart" ($2A) is only used if any game on that multicart actually uses expansion port devices. As these will be mostly Zapper games, emulating an expansion port Zapper together with two standard controllers is the simplest way of implementing this value.<br />
* The [[PowerPak]] official loader considers any .NES with a non-zero byte 15 to be invalid, and will fail to load the ROM. A [https://forums.nesdev.org/viewtopic.php?p=283943#p283943 patched N.MAP loader] is available.<br />
<br />
==Version History==<br />
* 2006-09-18 - Original version of specification by kevtris.<br />
** [https://forums.nesdev.org/viewtopic.php?p=17727#p17727 NES 2.0 "Official" Specification]<br />
* 2019-01-02 - Additions by NewRisingSun.<br />
** [https://forums.nesdev.org/viewtopic.php?f=3&t=17213&start=45#p220624 Additions proposal by NewRisingSun]<br />
** Flags 7: adds [[#Extended Console Type|Extended Console Type]] value<br />
** Flags 12: adds [[#CPU/PPU Timing|Dendy]] value<br />
** Flags 13: adds [[#Extended Console Type|Extended Console Type]] field<br />
** Flags 14: adds [[#Miscellaneous ROM Area|miscellaneous ROM]] specifier<br />
** Flags 15: adds [[#Default Expansion Device|Default Expansion Device]]<br />
<br />
==See Also==<br />
* [[NES 2.0 submappers]] - disambiguation for mappers that were under-specified in iNES 1<br />
* [[NES 2.0 header for ca65]] - macro header generator for ca65 assembly<br />
* [[NES 2.0 header for cc65]] - macro header generator for cc65 C code<br />
<br />
==References==<br />
* [https://forums.nesdev.org/viewtopic.php?p=17727#p17727 Original proposal by kevtris]<br />
* [https://forums.nesdev.org/viewtopic.php?f=3&t=17213&start=45#p220624 Additions proposal by NewRisingSun]<br />
* [https://forums.nesdev.org/viewtopic.php?t=19940 NES 2.0 XML Database, with link to Python script for applying it to a ROM files collection]<br />
<references/><br />
[[Category:File formats]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=User:Fiskbit&diff=21644User:Fiskbit2024-03-05T02:59:35Z<p>Fiskbit: /* Famicom (RF) */ Adds the newly-discovered HVC-CPU-02 board.</p>
<hr />
<div>I'll be staging information here before finding a place to move it to on the wiki.<br />
<br />
== CPU / APU ==<br />
<br />
=== Behavior ===<br />
<br />
* When the CPU comes out of reset, it is random whether it is aligned on the first or second half of an APU cycle (and thus random whether it begins on a GET or PUT cycle).<br />
* The state of the CPU's OUT pins is only updated when transitioning from a GET to PUT cycle. Thus, changes to OUT state lasting only 1 cycle (such as when toggled with an INC instruction) may be missed by the joypad device. This can be used to determine CPU/APU alignment, but poses a problem for expansion port devices that use OUT bits to signal when to snoop the data bus.<br />
* Readable APU registers ($4015 and, if modded, the test registers) drive the internal CPU bus, but not the external CPU bus, so they do not affect external open bus state. Therefore, a dummy read from one of these registers on the cycle before a read from external open bus (such as by using page crossing on an indexed read) will not change the external open bus value.<br />
* The CPU clock divider is not affected by reset. Therefore, resetting the CPU does not change CPU/PPU sub-cycle alignment.<br />
<br />
=== APU register reads ===<br />
<br />
The CPU has an internal address bus onto which separate 6502, OAM DMA, and DMC DMA buses are multiplexed. APU registers can only be read when bits [15:5] of the 6502 address bus match the $4000-$401F range. When they match during a read, bits [4:0] of the internal CPU address bus will be checked for a matching register. If those bits are $16 or $17, the relevant joypad is clocked, and if they are $15 or the CPU test pin is asserted, the internal data bus is isolated from the external data bus (preventing the register read from affecting external open bus) and fed from any matching APU register.<br />
<br />
Some unexpected edge cases result from this. Whether APU registers can be read depends on whether the 6502 address bus is in the APU register range, so if it is not, then OAM DMA from the $4000-40FF page will be unable to read them and will not clock joypads. However, if it is in that range when DMA occurs (because the CPU is currently executing from or reading from this range), then any DMA from an address with bits [4:0] matching a readable register or with the test pin asserted will trigger a register read, either overriding the value that would normally be read by the DMA or, in the case of non-test joypad reads, potentially causing a bus conflict.<br />
<br />
This has relevance to real workloads. If a joypad register is read at the same time as a DMC DMA from an address matching an APU register, the DMA will perform a register read, possibly with a bus conflict. Though not yet tested, this should also be able to cause an additional joypad clock, at least for the other joypad (as it is unknown whether additional same-joypad reads are ignored if on consecutive cycles). Thus, an audible glitch may occur if using the repeated-read method of avoiding joypad bit deletion.<br />
<br />
=== Revision differences ===<br />
<br />
==== Letterless ====<br />
<br />
* 4-cycle DMA glitches do not occur.<br />
<br />
== PPU ==<br />
<br />
=== Behavior ===<br />
<br />
==== OAM ====<br />
<br />
* Writes to OAM during rendering are ignored.<br />
* Disabling rendering outside of vblank can cause OAM to be corrupted when rendering next begins. If the disable write occurs approximately in the ranges of dots 0-125 or 254-318, then 2 sprite tiles (1 row) will be corrupted with the value of row 0 when rendering is next enabled. If the disable write occurs in the range 126-253 and rendering is enabled again outside of vblank, then corruption can occur on some CPU/PPU alignments, though this corruption is poorly understood. Dots 319-340 appear safe under all circumstances. This behavior also applies to the rendering-disable caused by resetting the PPU, so the first rendered frame after a PPU reset is likely to have OAM corruption. Note that these values may not be exact to the dot.<br />
* Signal reflection from a cartridge on the CPU data lines can cause OAM to corrupt. Cartridges with long or thin traces should include 30-100 ohm termination resistors in-series on these lines to suppress signal reflection. This issue has been observed on the FDS, PowerPak, and original Everdrive N8. https://forums.nesdev.org/viewtopic.php?p=232140#p232140<br />
<br />
==== Palettes ====<br />
<br />
* On revisions that support reading from palette RAM, doing so via the PPUDATA register at the same time as forced greyscale, as seen in the NTSC border at dot 326, disables forced greyscale for that dot, presumably to prevent the greyscale from clearing the low 4 bits of the value. Greyscale is actually forced everywhere outside of draw range, but can only be seen at the start of the border.<br />
* Reads from palette RAM do not set bits 7-6, so these will return PPU open bus.<br />
* The [[PPU palettes|background palette hack]] ignores bit 14 of v.<br />
* When rendering ends at the end of scanline 239, if the value left in v from rendering points into palette RAM, the NTSC border on scanlines 240-241 will automatically display the color pointed to by v (the "background palette hack"). This can be seen in the first corridor of Metal Storm.<br />
* The auto-increment behavior when writing to $2007 is delayed 1 dot after the write becomes effective. This means writing to palette RAM will show the newly-written color for 1 dot before advancing to the next color.<br />
* Disabling rendering mid-screen appears to be capable of corrupting palette RAM, but the specifics are not yet entirely known. The corrupted entry appears to depend on the value of v. https://forums.nesdev.org/viewtopic.php?f=2&t=23209<br />
<br />
==== Fetching ====<br />
<br />
* Writing to v on the first dot of a fetch can result in the low 8 bits being latched from the old v and the high 6 bits coming from the new v, resulting in a fetch from the wrong location. This can happen naturally at dot 258, where the low bits latch on dot 257 before the horizontal component of v is updated and the high bits on 258 after the update. Note that this applies to all fetches, but should only result in mixed addresses on nametable and attribute table fetches.<br />
<br />
==== Miscellaneous ====<br />
<br />
* The PPU clock divider is affected by reset. Therefore, resetting the PPU changes the CPU/PPU sub-cycle alignment.<br />
* PPU writes have some amount of delay before they take effect, depending on things like where the feature is used in the pixel pipeline and potentially the CPU/PPU cycle alignment. For example, greyscale is applied at the end of the pipeline and is thus approximately instant, while writes to $2006 appear to delay about 3 dots and toggling rendering delays about 4 dots. Note that these amounts are not necessarily exact. Battletoads relies on the rendering toggle delay to skip a vertical increment; without the delay, the extra increment causes a sprite 0 hit to miss, hanging the game.<br />
<br />
=== Revision differences ===<br />
<br />
==== 2C02A ====<br />
<br />
* Writes to $2001 disrupt rendering similar to toggling it off and on.<br />
* PPU bus write timing differs from later revisions in a way that causes graphical corruption on some modern cartridges, such as the Everdrive Pro. (Contemporary cartridges seem unaffected.)<br />
* On scanlines where sprite tiles are drawn, sprite pixels may be erroneously drawn at X=255.<br />
<br />
==== 2C02B ====<br />
<br />
* On scanlines where sprite tiles are drawn, sprite pixels may be erroneously drawn at X=255.<br />
<br />
== Mappers ==<br />
<br />
=== MMC3 ===<br />
<br />
* The scanline counter clocks when A12 rises after at least 3 M2 clocks with PPU A12 low.<br />
* With background using the $1000 table, the scanline counter behavior depends on the aborted fetch performed by the PPU on the idle dot. The skipped dot on the prerender scanline can cause an extra clock because it overrides this dot 0 behavior, creating a large enough window with PPU A12 low for 3 M2 clocks to fit on some CPU/PPU whole-cycle alignments.<br />
* Writing to $C001, clocking the counter, and writing to $C001 again will cause the counter to be OR'ed with value $80 on the next clock and neither decremented nor reloaded.<br />
<br />
=== MMC5 ===<br />
<br />
* The in-frame flag isn't set until the same address is fetched 3 times in a row, which occurs during the 3rd fetch for a scanline. This causes the first 3 fetches when using extended attributes to read incorrect data.<br />
* Because disabling rendering causes the in-frame flag to clear, updating palettes mid-frame will also trigger incorrect fetches when using extended attributes.<br />
<br />
=== TV-NET MC-1200 ===<br />
<br />
==== Address space ====<br />
<br />
$5000-57FF: VRAM window bank<br />
$6000-6FFF: TV-NET registers<br />
$7000-7FFF: Game card RAM bank<br />
$8000-BFFF: First 4 game card or firmware ROM banks<br />
$C000-DFFF: Game card or firmware ROM banks<br />
$E000-EFFF: Firmware ROM bank<br />
$F000-FFFF: Last firmware bank<br />
<br />
$8000-DFFF map firmware banks if a game card is not present.<br />
<br />
==== Registers ====<br />
<br />
8 registers, mirrored across $6000-6FFF. These are work-in-progress. <br />
<br />
===== UART register select ($6000) =====<br />
<br />
Write:<br />
* Register $00 seems to be incoming (serial?) data bytes when read, outgoing data bytes when written.<br />
* Register $02 seems like a 1-hot encoded status when read, $04 means something to do with data transmission, $02 some other special condition.<br />
* Register $05 seems to have something to do with the incoming and outgoing data validity?<br />
** Bits 1, 2, and 3 are to do with incoming data.<br />
** Bits 5 and 6 are to do with outgoing data.<br />
Read:<br />
* Possibly required after selecting a register but before reading from that register? Could be purely timing effects, or could be doing something else. Not required for writing to modem registers.<br />
<br />
===== UART data ($6001) =====<br />
<br />
Likely read/write data for register selected by $6000.<br />
<br />
===== VRAM window bank / Game card status ($6002) =====<br />
<br />
Write: 2 KB VRAM window bank. Unknown if bit 0 ignored.<br /><br />
Read: $00 if a game card is present and non-$00 otherwise.<br />
<br />
===== Game card ROM bank ($6003) =====<br />
<br />
7 bit 0<br />
---- ----<br />
xxDD DDDx<br />
|| |||<br />
++-+++-- Game card ROM bank at $C000-DFFF.<br />
<br />
Unknown if bit 0 ignored.<br />
<br />
===== Game card RAM bank ($6004)=====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xDDD<br />
|||<br />
+++- Game card RAM bank at $7000-7FFF.<br />
<br />
===== Firmware ROM bank ($6005) =====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xDDD<br />
|||<br />
+++- Firmware ROM bank at $E000-EFFF.<br />
<br />
===== VRAM window bank ($6006) =====<br />
<br />
Appears to control what is mapped into the $5000-57FF window. Observed writes are 4 before writing to what appears to be 1 KB of special graphics memory (MMC5-style ExRAM?) at $5000 and 3 after, and 5 to map in CHR-RAM, which is 32 KB and can be banked using $6002 in 1 KB amounts (unknown if bit 0 ignored).<br />
<br />
==== Game card connector ====<br />
<br />
Card | | TV-NET <br />
-----+--+--------<br />
1 |--| GND<br />
2 | | n/c<br />
3 |--| +5Vcc<br />
4 |<-| /CS<br />
5 |<-| RAM/ROM<br />
6 |<-| R/W<br />
7 |<-| ROM /OE<br />
8 |<>| CPU D0<br />
9 |<>| CPU D1<br />
10 |<>| CPU D2<br />
11 |<>| CPU D3<br />
12 |<>| CPU D4<br />
13 |<>| CPU D5<br />
14 |<>| CPU D6<br />
15 |<>| CPU D7<br />
16 |<-| CPU A0<br />
17 |<-| CPU A1<br />
18 |<-| CPU A2<br />
19 |<-| CPU A3<br />
20 |<-| CPU A4<br />
21 |<-| CPU A5<br />
22 |<-| CPU A6<br />
23 |<-| CPU A7<br />
24 |<-| CPU A8<br />
25 |<-| CPU A9<br />
26 |<-| CPU A10<br />
27 |<-| CPU A11<br />
28 |<-| A12<br />
29 |<-| A13<br />
30 |<-| A14<br />
31 |<-| A15<br />
32 |<-| A16<br />
33 |<-| A17<br />
34 |--| n/c in JRA-PAT, +5Vcc in MC-1200 host<br />
35 |<-| /RAMSEL<br />
36 |--| +5Vcc<br />
37 |->| Card /present<br />
38 |--| GND<br />
<br />
RAM/ROM selects whether /CS is sent to RAM or ROM. If it is sent to ROM, /RAMSEL is send to RAM.<br /><br />
Card /present affects /CE for the TV-NET firmware ROM and tells the mapper it's present via U6.98.<br />
<br />
==== Game card header ====<br />
<br />
Game cards are expected to have a pointer at $8000-8001 to a validation signature that must match a string at $F223 in the firmware, null-terminated on the firmware side. The game card start vector is located at $8004-8005.<br />
<br />
== Consoles ==<br />
Information about different console models, revisions, and behaviors. Still a long way to go here. Ideally, complex consoles like the Famicom Titler and FamicomBox would be broken out into their own pages.<br />
=== RF Famicom (HVC-001) ===<br />
Joypads clock once per read cycle instead of once per consecutive set of read cycles.<br />
<br />
CPU revisions:<br />
* RP2A03: letterless, E, G<br />
PPU revisions:<br />
* RP2C02: letterless, A, B, C, D, D-0, E-0, G-0<br />
* RC2C02: C<br />
Motherboard revisions:<br />
* HVC-CPU-01<br />
* HVC-CPU-02 (CPU: letterless, PPU: A)<br />
* HVC-CPU-03<br />
* HVC-CPU-04<br />
* HVC-CPU-05<br />
* HVC-CPU-06<br />
* HVC-CPU-07<br />
* HVC-CPU-08<br />
* HVC-CPU-GPM-01<br />
* HVC-CPU-GPM-02<br />
<br />
Letterless CPUs appear to be used on revisions 01-06, E starting with 06, and G on 07 and later. Revision A PPUs were used on revisions 01-05, with B and D both appearing on 05-06.<br />
<br />
=== Famicom (RF, Hong Kong) ===<br />
A PAL Famicom using NTSC chips, with a 50 Hz / 60 Hz switch. The master clock is 21.3125MHz. When in 50 Hz ("Slow") mode, a Nintendo N NPC26 chip slows the PPU by stopping its clock sometime between the end of rendering and the start of vblank, inserting 50 scanlines. If the CPU accesses the PPU during this time, it is allowed to run again briefly to handle the access, shortening the length of the frame.<br />
<br />
CPU revisions:<br />
* RP2A03: G<br />
PPU revisions:<br />
* RP2C02: G-0<br />
Motherboard revisions:<br />
* HVC-CPU-NPC-18-01<br />
* HVC-CPU-NPC-26-01<br />
<br />
=== Famicom (AV) ===<br />
CPU revisions:<br />
* RP2A03: G, H<br />
PPU revisions:<br />
* RP2C02: G-0, H-0<br />
Motherboard revisions:<br />
* HVCN-CPU-01<br />
* HVCN-CPU-02<br />
<br />
=== Twin Famicom AN-500 ===<br />
Combination Famicom/FDS console.<br />
<br />
CPU revisions:<br />
* RP2A03: E<br />
PPU revisions:<br />
* RP2C02: E-0<br />
<br />
=== Twin Famicom AN-505 ===<br />
Combination Famicom/FDS console with turbo controllers.<br />
<br />
=== Famicom Titler AN-510 ===<br />
An RGB console with a built-in video titler. Features various buttons and a resistive touch panel.<br />
<br />
CPU Revisions:<br />
* RP2A03: G<br />
PPU Revisions:<br />
* RC2C05: -99<br />
Motherboard revisions:<br />
* K6285DE<br />
* K6285DE /2\<br />
<br />
Note that the revisions are indicated within a numbered triangle next to the PCB revision.<br />
<br />
=== Sharp C1 TV ===<br />
<br />
=== Dataship 1200 ===<br />
A combination Famicom and Famicom Network System, but without a Famicom cartridge slot or standard controllers. Features a 14-pin Centronics port for interfacing with a printer, not present on a standard Famicom Network System modem. Compatible printers include the Chinon IJK-112 with a IF-1122 cable and the NEC PC-PR102TL3 with a PC-8894 cable. Uses a [[User:Ben_Boldt|Ricoh RF5GH05]] to handle the Centronics port as well as generate /ROMSEL, CPU RAM /CE, and PPU /CE.<br />
<br />
CPU revisions:<br />
* RP2A03: G<br />
PPU revisions:<br />
* RP2C02: G-0<br />
Motherboard revisions:<br />
* K4013800B<br />
* K4013800C<br />
<br />
=== FamicomBox ===<br />
Also released in Sharp FamicomStation branding. Features 16 cartridge slots, arranged into 3 groups of 5 and one additional primary slot, which can be selected between at runtime. Includes 8 KB of RAM at each of $0000-1FFF and $6000-7FFF and registers at $5000-5007 (mirrored through $5FFF). Offers various kinds of exceptions that can reset the console and return to the primary slot. Uses a 3198A CIC and will skip past slots that don't have one. Uses a 3199A coin timer, which can mix a beep into the audio out and trigger a screen-dimming effect of approximately 40% implemented in the RF modulator.<br />
<br />
CPU revisions:<br />
* RP2A03: E<br />
PPU revisions:<br />
* RP2C02: E-0<br />
<br />
Motherboard revisions:<br />
* SSS-CPU-03<br />
* SSS-CPU-04<br />
<br />
=== NES-001 ===<br />
CPU revisions:<br />
* RP2A03: E, G<br />
* RP2A07: letterless, A<br />
PPU revisions:<br />
* RP2C02: E-0, G-0<br />
* RP2A07: -0, A, A-0<br />
Motherboard revisions:<br />
* NES-CPU (01)<br />
* NES-CPU-02<br />
* NES-CPU-03<br />
* NES-CPU-04<br />
* NES-CPU-05<br />
* NES-CPU-06<br />
* NES-CPU-07<br />
* NES-CPU-08<br />
* NES-CPU-09<br />
* NES-CPU-10<br />
* NES-CPU-11<br />
* K6529WE (Sharp NES TV)<br />
<br />
Revision E chipsets appear to be featured on revisions 01-04, while G chipsets appear on 05-11 and the Sharp NES TV.<br />
<br />
=== NES-001 (NWC) ===<br />
The Nintendo World Championships used a modified NES-001, adding a Champ1 rev.A board with a 4-pin RJ port. This board features two optoisolators and is wired internally to +RESET and Joypad 2 D3. Looking into the port, the pins are:<br />
+--+<br />
| +-+<br />
| +--+<br />
| 1| -- GND for optoisolators<br />
| 2| -- GND for optoisolators<br />
| 3| <- +RESET<br />
| 4| <- Joypad 2 /D3<br />
| +--+<br />
| +-+<br />
+--+<br />
<br />
=== NES-101 ===<br />
CPU revisions:<br />
* RP2A03: G, H?<br />
PPU revisions:<br />
* RP2C02: G-0, H-0?<br />
Motherboard revisions:<br />
* NESN-CPU-01<br />
* NESN-CPU-JIO-01<br />
* NESN-CPU-AV-01<br />
<br />
=== M82 ===<br />
Uses a custom ASIC, the 274 Nintendo RCA Z IRSI.<br />
<br />
CPU revisions:<br />
* RP2A03: G<br />
* RP2A07: letterless<br />
PPU revisions:<br />
* RP2C02: G-0<br />
* RP2C07: Unknown<br />
Motherboard revisions:<br />
* IRS-45-003 Rev.F<br />
<br />
== Research topics ==<br />
<br />
* Disabling rendering mid-screen is capable of corrupting palette RAM, depending in some way on the value of v. This appears to only occur on some CPU/PPU alignments. All NTSC PPU revisions are believed to be affected, and PAL and RGB PPUs have not yet been tested. [https://forums.nesdev.org/viewtopic.php?f=2&t=23209 Reference: Problem with palette discoloration when PPU is turned off during rendering.]<br />
* NTSC and RGB PPUs prior to revision C have a bug where scanlines with sprites on them may also have sprite pixels mistakenly drawn at X=255. These might be tied to specific OAM rows.<br />
* DMC DMA timing on PAL may not be properly understood. Timing in the Years Behind demo differs between emulator and console.<br />
* Disabling rendering mid-screen can cause OAM corruption when rendering is reenabled, regardless of whether OAM DMA was performed in between and even across a PPU reset. The corruption behavior depends on where in the scanline rendering turns off. These regions are approximately dots 1-128, 129-256, and 257-320. The first and last regions appear to cause a row to be replaced with the data from row 0, while the middle region's corruption is not understood and appears to only occur if rendering is reenabled at certain positions within a dot (that is, only on certain CPU/PPU alignments and not if rendering enables at the beginning of a dot, such as at the start of the frame). PPUs prior to revision E seem to only show glitches for the 129-256 region. [https://forums.nesdev.org/viewtopic.php?p=248607#p248607 Reference: Isolated Warrior unemulated graphical glitche]<br />
* Changing CHR banks on MMC3 appears to be able to cause gliltchy slivers, but what data is being displayed is not known. [https://forums.nesdev.org/viewtopic.php?p=248525#p248525 Reference: Isolated Warrior unemulated graphical glitches]<br />
* The 'signal reflection' issue where a cartridge's effects on the CPU data lines can cause PPU OAM corruption is not fully understood and may be related in part to flash hardware in modern cartridges compared to contemporary ROMs. Resistors on all 8 CPU data lines near the cartridge do appear to fix this problem, but solutions that don't require this extra hardware would be preferred and so further research is warranted.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=CCU_v2.00_CF30288_pinout&diff=21622CCU v2.00 CF30288 pinout2024-02-21T01:44:00Z<p>Fiskbit: Typo.</p>
<hr />
<div>[[Category: pinouts]]Camerica CCU: 28-pin 0.4" shrink PDIP marked "CCU_V2.00 CF30288 N X 9240 PHILLIPINES" (Mappers [[iNES Mapper 071|71]] and [[iNES Mapper 232|232]])<br />
<br />
.---v---.<br />
CPU M2 -> |01 28| ??<br />
CPU D4 -> |02 27| ??<br />
CPU D3 -> |03 26| ??<br />
CPU D2 -> |04 25| ??<br />
CPU D1 -> |05 24| -> ROM /OE<br />
CPU D0 -> |06 23| ??<br />
VCC -- |07 22| -- GND<br />
CPU A0 -> |08 21| -> CIC STUN<br />
CPU A13 -> |09 20| -> $C000.3 OR CPU A14<br />
CPU A14 -> |10 19| -> $8000.3<br />
/ROMSEL -> |11 18| -> $C000.2 OR CPU A14<br />
CPU R/W -> |12 17| -> $8000.4<br />
?? |13 16| -> $C000.1 OR CPU A14<br />
?? |14 15| -> $C000.0 OR CPU A14<br />
'-------'<br />
28-pin 0.4" shrink DIP<br />
<br />
Notes:<br />
* This chip is used in ''Aladdin Deck Enhancer 1.1/2.0'' and ''Super Sports Challenge''<br />
* CIC STUN pin is used only in ''Aladdin Deck Enhancer 1.1''<br />
<br />
* Source: [http://forums.nesdev.org/viewtopic.php?f=9&t=19781&p=273471#p247213]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Patents&diff=21598Patents2024-02-09T07:17:21Z<p>Fiskbit: Fixes links, which were all dead.</p>
<hr />
<div>{| border="1" cellpadding="1" class="wikitable sortable" style=<br />
!width=""|Patent No.<br />
!width=""|Title<br />
!width=""|Inventor<br />
!width=""|Asignee<br />
!width=""|Filing date<br />
!width=""|Issue date<br />
!width=""|Notes<br />
|-<br />
|[https://patents.google.com/patent/US4745478A 4745478]<br />
|RF switch<br />
|Katsuya Nakagawa et al<br />
|Nintendo Co., Ltd.<br />
|1985-08-01<br />
|1988-05-17<br />
|RF switch<br />
|-<br />
|[https://patents.google.com/patent/US4687200A 4687200]<br />
|Multi-directional switch<br />
|Ichiro Shirai<br />
|Nintendo Co., Ltd.<br />
|1985-08-09<br />
|1987-08-18<br />
|D-Pad<br />
|-<br />
|[https://patents.google.com/patent/USD294020S D294020]<br />
|Cartridge for game machine<br />
|Masayuki Yukawa<br />
|Nintendo Co., Ltd.<br />
|1985-10-07<br />
|1988-02-02<br />
|Cartridge design<br />
|-<br />
|[https://patents.google.com/patent/USD296347S D296347]<br />
|Game robot<br />
|Makoto Kanoh<br />
|Nintendo Co., Ltd.<br />
|1985-11-04<br />
|1988-06-21<br />
|R.O.B. design<br />
|-<br />
|[https://patents.google.com/patent/USD299726S D299726]<br />
|Video game control unit<br />
|Masayuki Yukawa<br />
|Nintendo Co., Ltd.<br />
|1985-11-04<br />
|1989-02-07<br />
|NES design<br />
|-<br />
|[https://patents.google.com/patent/US4799635A 4799635]<br />
|System for determining authenticity of an external memory used in an information processing apparatus<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1985-12-23<br />
|1989-01-24<br />
|NES w/ software authentication<br />
|-<br />
|[https://patents.google.com/patent/US4729563A 4729563]<br />
|Robot-like game apparatus<br />
|Gunpei Yokoi<br />
|Nintendo Co., Ltd.<br />
|1985-12-24<br />
|1988-03-08<br />
|R.O.B.<br />
|-<br />
|[https://patents.google.com/patent/US4860128A 4860128]<br />
|Recordable data device having identification symbols formed thereon and cooperating data processing system having registering symbols<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1986-04-24<br />
|1989-08-22<br />
|FDS diskette<br />
|-<br />
|[https://patents.google.com/patent/US4783812A 4783812]<br />
|Electronic sound synthesizer<br />
|Yukio Kaneoka<br />
|Nintendo Co., Ltd.<br />
|1986-08-05<br />
|1988-11-08<br />
|Sound<br />
|-<br />
|[https://patents.google.com/patent/US4763300A 4763300]<br />
|Front loading apparatus for a memory cartridge utilized for a data processing machine<br />
|Masayuki Yukawa<br />
|Nintendo Co., Ltd.<br />
|1986-08-27<br />
|1988-08-09<br />
|Cartridge front-loading<br />
|-<br />
|[https://patents.google.com/patent/USD292399S D292399]<br />
|Cartridge for game machine<br />
|Masayuki Yukawa<br />
|Nintendo Co., Ltd.<br />
|1986-10-27<br />
|1987-10-20<br />
|Cartridge design<br />
|-<br />
|[https://patents.google.com/patent/USD308197S D308197]<br />
|Adaptor for a game machine cartridge<br />
|Yoshihiro Inoue<br />
|Nintendo Co., Ltd.<br />
|1987-01-09<br />
|1990-05-29<br />
|Famicom cartridge adaptor design<br />
|-<br />
|[https://patents.google.com/patent/US4824106A 4824106]<br />
|T.V. game system having reduced memory needs<br />
|Hiroo Ueda et al<br />
|Ricoh Co., Ltd., Nintendo Co., Ltd.<br />
|1987-02-12<br />
|1989-04-25<br />
|Image processing<br />
|-<br />
|[https://patents.google.com/patent/USD312081S D312081]<br />
|Cartridge for game machine<br />
|Masayuki Yukawa<br />
|Nintendo Co., Ltd.<br />
|1987-04-17<br />
|1990-11-13<br />
|Cartridge design<br />
|-<br />
|[https://patents.google.com/patent/US4844465A 4844465]<br />
|Adaptor of a cartridge for gaming machine<br />
|Toshiro Hibino et al<br />
|Nintendo Co., Ltd.<br />
|1987-04-17<br />
|1989-07-04<br />
|Famicom cartridge adaptor design<br />
|-<br />
|[https://patents.google.com/patent/US4926372A 4926372]<br />
|Memory cartridge bank selecting<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1987-05-05<br />
|1990-05-15<br />
|MMC<br />
|-<br />
|[https://patents.google.com/patent/US4813682A 4813682]<br />
|Video target control and sensing circuit for photosensitive gun<br />
|Satoru Okada<br />
|Nintendo Co., Ltd.<br />
|1987-06-10<br />
|1989-03-21<br />
|Zapper Light Gun<br />
|-<br />
|[https://patents.google.com/patent/US4922420A 4922420]<br />
|Video game software selection data processing system<br />
|Katsuya Nakagawa et al<br />
|Nintendo Co., Ltd.<br />
|1987-06-23<br />
|1990-05-01<br />
|PlayChoice-10<br />
|-<br />
|[https://patents.google.com/patent/USD317913S D317913]<br />
|Adaptor for game machine cartridge<br />
|Yoshihiro Inoue<br />
|Nintendo Co., Ltd.<br />
|1987-10-05<br />
|1991-07-02<br />
|Famicom cartridge adaptor design<br />
|-<br />
|[https://patents.google.com/patent/USD307921S D307921]<br />
|Joy stick controller for video game<br />
|Lance N. Barr<br />
|Nintendo of America Inc.<br />
|1987-10-13<br />
|1990-05-15<br />
|NES Advantage design<br />
|-<br />
|[https://patents.google.com/patent/US4949298A 4949298]<br />
|Memory cartridge having a multi-memory controller with memory bank switching capabilities and data processing apparatus<br />
|Yoshiaki Nakanishi et al<br />
|Nintendo Co., Ltd.<br />
|1987-11-12<br />
|1990-08-14<br />
|Cartridge w/ MMC<br />
|-<br />
|[https://patents.google.com/patent/US4865321A 4865321]<br />
|Memory cartridge and information processor unit using such cartridge<br />
|Katsuya Nakagawa et al<br />
|Nintendo Co., Ltd.<br />
|1987-11-27<br />
|1989-09-12<br />
|Cartridge<br />
|-<br />
|[https://patents.google.com/patent/US4815733A 4815733]<br />
|Photosensing video game control system<br />
|Gunpei Yokoi<br />
|Nintendo Co., Ltd.<br />
|1988-02-23<br />
|1989-03-28<br />
|R.O.B.<br />
|-<br />
|[https://patents.google.com/patent/US5014982A 5014982]<br />
|Memory cartridge and game apparatus using the same<br />
|Satoru Okada et al<br />
|Nintendo Co., Ltd.<br />
|1988-08-24<br />
|1991-05-14<br />
|Password system<br />
|-<br />
|[https://patents.google.com/patent/US5070479A 5070479]<br />
|External memory having an authenticating processor and method of operating same<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1989-01-13<br />
|1991-12-03<br />
|NES w/ software authentication<br />
|-<br />
|[https://patents.google.com/patent/USD324244S D324244]<br />
|Adapter housing for a video game control deck<br />
|Christopher Stamper et al<br />
|Nintendo of America Inc.<br />
|1989-02-22<br />
|1992-02-25<br />
|Four controller port adapter design<br />
|-<br />
|[https://patents.google.com/patent/US4918434A 4918434]<br />
|T.V. game system<br />
|Hiroo Ueda et al<br />
|Nintendo Co., Ltd., Ricoh Co., Ltd.<br />
|1989-04-25<br />
|1990-04-17<br />
|Image processing<br />
|-<br />
|[https://patents.google.com/patent/USD326117S D326117]<br />
|Hands free controller for video games<br />
|Lance Barr et al<br />
|Nintendo of America Inc.<br />
|1989-06-20<br />
|1992-05-12<br />
|HFC design<br />
|-<br />
|[https://patents.google.com/patent/US5007256A 5007256]<br />
|Cartridge operated entertainment system with removal deterrent device for preventing unauthorized use<br />
|Thomas E. Lowe<br />
|Thomas E. Lowe<br />
|1989-09-20<br />
|1991-04-16<br />
|Cartridge lock device<br />
|-<br />
|[https://patents.google.com/patent/US5004232A 5004232]<br />
|Computer game cartridge security circuit<br />
|John J. Wong et al<br />
|Macronix, Inc.<br />
|1989-10-13<br />
|1991-04-02<br />
|Software authentication bypass<br />
|-<br />
|[https://patents.google.com/patent/USD325049S D325049]<br />
|Video game remote control signal receiver<br />
|John P. Cordell<br />
|Nintendo of America Inc.<br />
|1989-11-27<br />
|1992-03-31<br />
|NES Satellite design<br />
|-<br />
|[https://patents.google.com/patent/USD322242S D322242]<br />
|Remote control transmitter<br />
|John P. Cordell<br />
|Nintendo of America Inc.<br />
|1989-11-27<br />
|1991-12-10<br />
|NES Satellite design<br />
|-<br />
|[https://patents.google.com/patent/US5025526A 5025526]<br />
|Apparatus for cleaning electronic game consoles and cartridges<br />
|Norio Ichitsubo et al<br />
|Nintendo of America Inc.<br />
|1989-12-13<br />
|1991-06-25<br />
|NES Cleaning Kit<br />
|-<br />
|[https://patents.google.com/patent/US5148572A 5148572]<br />
|Video game console and cartridge cleaning kit<br />
|James M. Wells et al<br />
|James M. Wells et al<br />
|1989-12-20<br />
|1992-09-22<br />
|Cleaning Kit<br />
|-<br />
|[https://patents.google.com/patent/USD327918S D327918]<br />
|Multi-user adaptor for a video game<br />
|John Cordell<br />
|Nintendo of America Inc.<br />
|1989-12-27<br />
|1992-07-14<br />
|NES Four Score design<br />
|-<br />
|[https://patents.google.com/patent/US4984193A 4984193]<br />
|Memory cartridge<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1989-12-29<br />
|1991-01-08<br />
|MMC<br />
|-<br />
|[https://patents.google.com/patent/US5276831A 5276831]<br />
|Memory cartridge having a multi-memory controller with memory bank switching capabilities and data processing apparatus<br />
|Yoshiaki Nakanishi et al<br />
|Nintendo Co., Ltd.<br />
|1990-05-24<br />
|1994-01-04<br />
|MMC<br />
|-<br />
|[https://patents.google.com/patent/US5125671A 5125671]<br />
|T.V. game system having reduced memory needs<br />
|Hiroo Ueda et al<br />
|Ricoh Co., Ltd., Nintendo Co., Ltd.<br />
|1990-06-07<br />
|1992-06-30<br />
|Image processing<br />
|-<br />
|[https://patents.google.com/patent/US5226136A 5226136]<br />
|Memory cartridge bank selecting apparatus<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1990-11-05<br />
|1993-07-06<br />
|MMC<br />
|-<br />
|[https://patents.google.com/patent/US5243730A 5243730]<br />
|Apparatus for cleaning electronic game consoles and cartridges<br />
|Norio Ichitsubo et al<br />
|Nintendo of America Inc.<br />
|1991-04-08<br />
|1993-09-14<br />
|NES Cleaning Kit<br />
|-<br />
|[https://patents.google.com/patent/US5291189A 5291189]<br />
|Direct memory access apparatus in image processing system and external storage device used therein<br />
|Masahiro Otake et al<br />
|Nintendo Co., Ltd., Ricoh Co., Ltd.<br />
|1991-08-26<br />
|1994-03-01<br />
|DMA<br />
|-<br />
|[https://patents.google.com/patent/US5317714A 5317714]<br />
|Digital sound source apparatus and external memory cartridge used therefor<br />
|Katsuya Nakagawa et al<br />
|Nintendo Co., Ltd.<br />
|1991-09-02<br />
|1994-05-31<br />
|Sound<br />
|-<br />
|[https://patents.google.com/patent/USRE34161E RE34161]<br />
|Memory cartridge and information processor unit using such cartridge<br />
|Katsuya Nakagawa et al<br />
|Nintendo Co., Ltd.<br />
|1991-09-10<br />
|1993-01-12<br />
|Cartridge front-loading<br />
|-<br />
|[https://patents.google.com/patent/US5181965A 5181965]<br />
|Method of cleaning electrical contacts for computer and video games<br />
|Louis J. Bakanowsky et al<br />
|Curtis Manufacturing Company, Inc.<br />
|1992-05-12<br />
|1993-01-26<br />
|Cleaning kit<br />
|-<br />
|[https://patents.google.com/patent/US5308086A 5308086]<br />
|Video game external memory arrangement with reduced memory requirements<br />
|Hiroo Ueda et al<br />
|Ricoh Co., Ltd., Nintendo Co., Ltd.<br />
|1992-06-19<br />
|1994-05-03<br />
|Image processing<br />
|-<br />
|[https://patents.google.com/patent/US5469191A 5469191]<br />
|Cursor control system<br />
|Jay Smith et al<br />
|Jay Smith et al<br />
|1992-11-30<br />
|1995-11-21<br />
|Videomation<br />
|-<br />
|[https://patents.google.com/patent/US5265888A 5265888]<br />
|Game apparatus and memory cartridge used therefor<br />
|Masao Yamamoto et al<br />
|Nintendo Co., Ltd.<br />
|1993-02-19<br />
|1993-11-30<br />
|Dr. Mario<br />
|-<br />
|[https://patents.google.com/patent/US5395112A 5395112]<br />
|Memory cartridge<br />
|Richard Darling<br />
|Codemasters Limited<br />
|1993-04-05<br />
|1995-03-07<br />
|Game Genie<br />
|-<br />
|[https://patents.google.com/patent/US5426762A 5426762]<br />
|System for determining a truth of software in an information processing apparatus<br />
|Katsuya Nakagawa<br />
|Nintendo Co., Ltd.<br />
|1993-04-07<br />
|1995-06-20<br />
|NES w/ software authentication<br />
|-<br />
|[https://patents.google.com/patent/US5435573A 5435573]<br />
|Wireless remote control and position detecting system<br />
|Howerd Oakford<br />
|Visioneering International, Inc.<br />
|1993-04-13<br />
|1995-07-25<br />
|U-Force?<br />
|-<br />
|[https://patents.google.com/patent/USD350782S D350782]<br />
|Controller for video game machine<br />
|Lance Barr<br />
|Nintendo of America Inc.<br />
|1993-05-24<br />
|1994-09-20<br />
|Unused controller design<br />
|-<br />
|[https://patents.google.com/patent/USD350992S D350992]<br />
|Electronic game housing<br />
|Lance Barr<br />
|Nintendo Co., Ltd.<br />
|1993-05-24<br />
|1994-09-27<br />
|NES-101 design<br />
|-<br />
|[https://patents.google.com/patent/US5337069A 5337069]<br />
|Still picture display apparatus and external storage device used therein<br />
|Masahiro Otake et al<br />
|Nintendo Co., Ltd., Ricoh Co., Ltd.<br />
|1993-11-16<br />
|1994-08-09<br />
|Scrolling<br />
|-<br />
|[https://patents.google.com/patent/US5560614A 5560614]<br />
|Video game system having reduced memory needs for a raster scanned display<br />
|Hiroo Ueda et al<br />
|Ricoh Co., Ltd., Nintendo Co., Ltd.<br />
|1994-03-22<br />
|1996-10-01<br />
|Image processing<br />
|-<br />
|[https://patents.google.com/patent/US5495266A 5495266]<br />
|Still picture display apparatus and external storage device used therein<br />
|Masahiro Otake et al<br />
|Nintendo Co., Ltd., Ricoh Co., Ltd.<br />
|1994-07-18<br />
|1996-02-27<br />
|Scrolling<br />
|-<br />
|[https://patents.google.com/patent/US5599232A 5599232]<br />
|Memory cartridge with interface having graphics co-processor<br />
|Richard Darling<br />
|Codemasters Limited<br />
|1994-10-06<br />
|1997-02-04<br />
|Game Genie<br />
|-<br />
|[https://patents.google.com/patent/USRE36675E RE36675]<br />
|Game apparatus and memory cartridge used therefor<br />
|Masao Yamamoto et al<br />
|Nintendo Co., Ltd.<br />
|1995-11-29<br />
|2000-04-25<br />
|Dr. Mario<br />
|}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Turbo_File&diff=21593Turbo File2024-02-03T04:14:21Z<p>Fiskbit: Grammar.</p>
<hr />
<div>The Turbo File (for [[Famicom|Family Computer]]) is a Famicom expansion port peripheral developed by ASCII Corporation, and is used to store save data for certain games. Variants of the device were also produced for the Game Boy (Turbo File GB), Game Boy Advance (Turbo File Advance), and Super Famicom (Turbo File Twin). Additionally, the Turbo File can be connected to a Super Famicom using an adapter cable, allowing certain SFC games to use the device.<br />
<br />
The device exists in two iterations; the original model (AS-TFO2) containing 8K of battery-backed SRAM and a write protect switch, and the Turbo File II (TFII) containing 32K of battery-backed SRAM (which is divided into four 8K banks that can be switched using a four-way SELECT switch, thus allowing for four game saves) as well as the write protect switch from the original. Both devices also have an LED that illuminates when connected to a Famicom that is powered on.<br />
<br />
Famicom games that support the Turbo File include:<br />
*''Best Keiba - Derby Stallion'' (1991)<br />
*''Best Play Pro Yakyuu II'' (1990)<br />
*''Best Play Pro Yakyuu Special'' (1992)<br />
*''Castle Excellent'' (1986)<br />
*''Derby Stallion - Zenkoku Ban'' (1992)<br />
*''Downtown - Nekketsu Monogatari'' (1989)<br />
*''Dungeon Kid'' (1990)<br />
*''Famicom Shougi - Ryuuousen'' (1991)<br />
*''Fleet Commander'' (1988)<br />
*''Haja no Fuuin'' (1987)<br />
*''Itadaki Street - Watashi no Mise ni Yottette'' (1990)<br />
*''The Money Game 2 - Kabutochou no Kiseki'' (1989)<br />
*''Ninjara Hoi!'' (1990)<br />
*''Wizardry - Legacy of Llylgamyn'' (1989)<br />
*''Wizardry - Proving Grounds of the Mad Overlord'' (1987)<br />
*''Wizardry - The Knight of Diamonds'' (1991)<br />
Most titles bear a "TF" logo on the cartridge label signifying their compatibility.<br />
<br />
Games that are believed to potentially work with the device (but remain unconfirmed) include:<br />
*''Castlequest'' (1989) (US version of ''Castle Excellent''.)<br />
*''Kunio 8-in-1'' (Pirate multicart that contains ''Downtown - Nekketsu Monogatari'' listed as "HEROS STORY" in the selection menu.)<br />
<br />
== Memory Setup and File Format ==<br />
The first byte of memory (offset 0000h) is unused, potentially out of fear that certain games with controller access might disrupt it, so a dummy byte is used to skip it after resetting the address. All the rest of the space (0001h-1FFFh) is used to store save data, with files being attached directly after each other. Invalid file IDs indicate the start of free memory.<br />
<br />
The majority of Turbo File games utilize this format for save files:<br />
2 ID "AB" (41h,42h)<br />
2 Filesize (16+N+2) (including title and checksum)<br />
16 Title in ASCII (terminated by 00h or 01h)<br />
N Data Portion<br />
2 Checksum (all N bytes in Data Portion added together)<br />
<br />
The exception to this, ''Castle Excellent'', uses a unique file format, shown here:<br />
1 Don't care (should be 00h) ;fixed, at offset 0001h<br />
2 ID AAh,55h ;fixed, at offset 0002h..0003h<br />
508 Data Portion (Data, end code "BEDEUTUN", followed by some unused bytes)<br />
This game also forgoes a filename and utilizes a hardcoded memory offset of 511 bytes (0001h-01FFh).<br />
Due to the hardcoded memory offset, ''Castle Excellent'' will destroy any other file that is located at the same address. Some later games for both the Famicom and Super Famicom (including ''Fleet Commander'') are able to properly manage the Castle Excellent save file.<br />
<br />
== Reference ==<br />
* nocash's NES documentation: https://problemkaputt.de/everynes.htm#storageturbofile<br />
<br />
[[Category:File formats]]<br />
[[Category:Hardware]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Color_$0D_games&diff=21579Color $0D games2024-01-26T16:39:06Z<p>Fiskbit: Replaces blown-out thumbnails with actual animated images. Slightly annoying, but less misleading / more useful.</p>
<hr />
<div>On an NES, the palette color $0D causes the signal to drop below the normal black level. This low voltage signal is sometimes mistaken by televisions for blanking signals, which can cause an unstable picture, or total picture loss on some devices. Other devices seem to process with signal without problem.<br />
<br />
== Games ==<br />
<br />
{| class="wikitable sortable"<br />
! style="width: 18%" | Game<br />
! class="unsortable" | Notes<br />
|-<br />
| ''Contra 100 in 1'' || Uses both for background color and one of the sprites' color; to apply a patch, change values at those offsets in ROM from $0D to $0F:<br />
$388B, $388F, $3893, $3897, $389B, $389C, $389F, $38A3, $38A7<br />
|-<br />
| ''Contra 168 in 1'' || Uses both for background color and one of the sprites' color; to apply a patch, change values at those offsets in ROM from $0D to $0F:<br />
$2451, $2455, $2459, $245D, $2461, $2462, 2465, $2469, $246D<br />
|-<br />
| ''Bee 52'' ||<br />
|-<br />
| ''Castelian'' ||<br />
|-<br />
| ''Cybernoid'' || $0D is used as the background color.<br />
|-<br />
| ''The Fantastic Adventures of Dizzy'' ||<br />
|-<br />
| ''FireHawk'' (USA) || Used in both the background and sprites. The European release (with NTSC video detection) corrects this.<br />
|-<br />
| ''Game Genie'' || The code entry screen uses it for its background.<br />
|-<br />
| ''The Immortal'' || Also uses all three de-emphasis bits to compensate for the the user cranking up the TV set's brightness so that regular black ($xE/$xF) can be used [https://youtu.be/Gsv3ci7ZChM as a darker shade of gray while color $0D is used as a black background color].<br />
|-<br />
| ''Indiana Jones and the Last Crusade'' (Taito) || Used as the background color in the motorcycle level.<br />
|-<br />
| ''Indiana Jones and the Last Crusade'' (Ubisoft) ||<br />
|-<br />
| ''Maniac Mansion'' (USA) || <br />
|-<br />
| ''Micro Machines'' ||<br />
|-<br />
| ''MIG-29 Soviet Fighter '' ||<br />
|-<br />
| ''Quattro Sports'' ||<br />
|-<br />
| ''Quattro Adventures'' ||<br />
|-<br />
| ''Skate or Die 2'' || Used as the background color during the introduction cutscene sequence.<br />
|-<br />
| ''The Super Shinobi'' || Unlicensed clone of Shinobi III.<br />
|-<br />
| ''Teenage Mutant Ninja Turtles'' || Uses it for black outlines on sprites, the lack of large areas of this color mitigates the problem.<br />
|-<br />
| ''The Three Stooges'' || Uses $xD colors that are turned to $0D during fades.<br />
|}<br />
<br />
== Effects ==<br />
<br />
[[File:Color_0d_-_contra_168.jpg|thumb|Modern LCD TV and modern famiclone (probably RS-35) showing distorded image in ''Contra 168-in-1'' cartridge]]<br />
<br />
[[File:Color_0d_-_super_robin_hood.jpg|thumb|Different modern LCD TV with digital famiclone (connected via HDMI) shows $0D color to be displayed as gray in ''Super Robin Hood'' game]]<br />
<br />
[[File:Color_0d_-_fantblue.gif|frame|Modern 29" CRT TV with IQ502 rev 2 (UM6561 nes-on-chip) famiclone shows periodic loss of v-sync when the paper unrolls at the beginning of ''Fantastic Adventures of Dizzy'' game. Note that this TV has no problems with displaying $0D colors with different famiclones, and even using this famiclone - this is the only moment in this game that the problem manifests, though this game uses this color all the time]]<br />
<br />
[[File:Color_0d_-_ultimate_stuntman.gif|frame|Same TV and console as above, No problems in the beginning screenshots, where $0d is used as universal background colors, while permanent v-sync loss during game, where $0d is used as blinking car's shadow color in ''Ultimate Stuntman'' game.]]<br />
<br />
<br />
Because the signal created by $0D is outside the specifications for the video signal, there is a lot of variation in how display devices handle it. Here are some possible effects that may be seen when using $0D:<br />
* $0D appears the same black as the other black colors (e.g. $0F).<br />
* $0D appears slightly darker than other blacks.<br />
* $0D appears as gray.<br />
* The device renormalizes the range when $0D appears, slightly brightening all other colours while it is onscreen.<br />
* Wobbly or distorted image from loss of horizontal blanking stability (either permanent or periodic)<br />
* Loss of vertical blanking stability.<br />
* Total loss of picture.<br />
<br />
These effects are more likely to occur when color $0D is used with the de-emphasis bits enabled, such as in ''The Immortal'', as seen in these [https://youtu.be/3fhyX3HdVcg example] [https://youtu.be/4Kli09cSGOU videos].<br />
<br />
== Workarounds ==<br />
* Patch the game code to replace all the $0D writes with $0F. This likely requires changes to many bytes in the ROM, so a Game Genie (limited to 3 changes) would not be sufficient. Instead, updated ROMs or a more capable pass-through patching device would likely be required<br />
* If your TV has digital inputs (for example - HDMI), use RCA to HDMI adapter, whose analog to digital converter might cope better with the out-of-spec video signal<br />
* Modify the console to use a different video output stage that adjusts the voltages so that the TV may accept it, such as by omitting the NPN transistor follower part of the video amplifier. However, the TV may ignore this voltage offset<br />
* Change your TV, console and/or video adapter (if you are using one)<br />
<br />
== Tests ==<br />
* [http://forums.nesdev.org/viewtopic.php?f=3&t=13264 Palette test ROM] - Displays NES palette, and can toggle $0D display.<br />
* [http://forums.nesdev.org/viewtopic.php?f=22&t=11255 NESPix] - Native graphics editor that allows use of $0D, and can test it in various visual arrangements.<br />
* [http://forums.nesdev.org/viewtopic.php?f=22&t=13394 240p test suite] - TV testing program. Test cards with $0D include PLUGE, SMPTE color bars, Solid color screen, and IRE. PLUGE also includes emphasized $0D.<br />
<br />
== See also ==<br />
* [[NTSC video]]<br />
* [[PPU palettes]]<br />
* [[Colour-emphasis games]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=MMC1&diff=21578MMC12024-01-26T06:08:49Z<p>Fiskbit: Adds a reference to a forum thread about the MMC MULTI CHECKER-02 development board.</p>
<hr />
<div>{{Infobox iNES mapper<br />
|name=MMC1<br />
|name2=SxROM<br />
|company=Nintendo, others<br />
|mapper=1<br />
|nescartdbgames=390<br />
|othermappers=[[iNES Mapper 105|105]], [[iNES Mapper 155|155]]<br />
|complexity=ASIC<br />
|boards=SKROM, SLROM,<br/>SNROM, others<br />
|pinout=MMC1 pinout<br />
|prgmax=256K (512K)<br />
|prgpage=16K + 16K fixed or 32K<br />
|wrammax=32K<br />
|wrampage=8K<br />
|chrmax=128K<br />
|chrpage=4K + 4K or 8K<br />
|mirroring=H, V, or 1, switchable<br />
|busconflicts=No<br />
}}<br />
[[Category:Nintendo licensed mappers]][[Category:NES 2.0 mappers with submappers]]<br />
The '''Nintendo MMC1''' is a [[MMC|mapper]] [[:Category:ASIC mappers|ASIC]] used in Nintendo's [[SxROM]] and [[NES-EVENT]] Game Pak boards. Most common SxROM boards are assigned to '''iNES Mapper 1'''. This chip first appeared in the April of 1987.<br />
<br />
== Banks ==<br />
* CPU $6000-$7FFF: 8 KB PRG RAM bank, (optional)<br />
* CPU $8000-$BFFF: 16 KB PRG ROM bank, either switchable or fixed to the first bank<br />
* CPU $C000-$FFFF: 16 KB PRG ROM bank, either fixed to the last bank or switchable<br />
* PPU $0000-$0FFF: 4 KB switchable CHR bank<br />
* PPU $1000-$1FFF: 4 KB switchable CHR bank<br />
<br />
Through writes to the MMC1 control register, it is possible for the program to swap the fixed and switchable PRG ROM banks or to set up 32 KB PRG bankswitching (like [[BNROM]]), but most games use the default setup, which is similar to that of [[UxROM]].<br />
<br />
== Interface ==<br />
Unlike almost all other mappers, the MMC1 is configured through a serial port in order to reduce its pin count. CPU $8000-$FFFF is connected to a common shift register.<br />
Writing a value with bit 7 set ($80 through $FF) to any address in $8000-$FFFF clears the shift register to its initial state.<br />
To change a register's value, the CPU writes five times with bit 7 clear and one bit of the desired value in bit 0 (starting with the low bit of the value).<br />
On the first four writes, the MMC1 shifts bit 0 into a shift register.<br />
On the fifth write, the MMC1 copies bit 0 and the shift register contents into an internal register selected by bits 14 and 13 of the address, and then it clears the shift register.<br />
Only on the fifth write does the address matter, and even then, only bits 14 and 13 of the address matter because the mapper doesn't see the lower address bits (similar to the mirroring seen with [[PPU registers]]). After the fifth write, the shift register is cleared automatically, so writing again with bit 7 set to clear the shift register is not needed.<br />
<br />
=== Examples ===<br />
----<br />
==== Shift register ====<br />
To switch a bank, a program will execute code similar to the following:<br />
<br />
<pre><br />
;<br />
; Sets the switchable PRG ROM bank to the value of A.<br />
;<br />
; A MMC1_SR MMC1_PB<br />
setPRGBank: ; 000edcba 10000 Start with an empty shift register (SR). The 1 is used<br />
sta $E000 ; 000edcba -> a1000 to detect when the SR has become full.<br />
lsr a ; >0000edcb a1000<br />
sta $E000 ; 0000edcb -> ba100<br />
lsr a ; >00000edc ba100<br />
sta $E000 ; 00000edc -> cba10<br />
lsr a ; >000000ed cba10<br />
sta $E000 ; 000000ed -> dcba1 Once a 1 is shifted into the last position, the SR is full.<br />
lsr a ; >0000000e dcba1 <br />
sta $E000 ; 0000000e dcba1 -> edcba A write with the SR full copies D0 and the SR to a bank register<br />
; 10000 ($E000-$FFFF means PRG bank number) and then clears the SR.<br />
rts<br />
</pre><br />
<br />
But because only the fifth write sets the destination register, the following equivalent (if [[Watermarking#Instruction encoding|obfuscated]]) subroutine changes the PRG ROM bank in the same manner:<br />
<br />
<pre><br />
setPRGBank:<br />
sta $8765<br />
lsr a<br />
sta $FACE<br />
lsr a<br />
sta $BA11<br />
lsr a<br />
sta $AD2E<br />
lsr a<br />
sta $EAD5<br />
rts<br />
</pre><br />
<br />
==== Reset ====<br />
To reset the mapper, which clears the shift register and sets the PRG ROM bank mode to 3 (fixing the last bank at $C000 and allowing the 16 KB bank at $8000 to be switched), one need only do a single write to any ROM address with a 1 in bit 7:<br />
<br />
<pre><br />
resetMapper:<br />
lda #$80<br />
sta $8000<br />
rts<br />
</pre><br />
<br />
Commonly, reset is done with an increment on a negative value to save 2 bytes. Because increment performs two writes, first writing the old value before the incremented one, it is recommended (such as for wider emulator compatibility) that the increment target a value that is negative on both writes, such as the INC opcode ($EE) itself:<br />
<br />
<pre><br />
resetMapper:<br />
inc resetMapper<br />
rts<br />
</pre><br />
<br />
Note that some games do a reset write to each of the 4 registers, even though it is only necessary to do 1 reset write to any register. It is suspected these games do this because of discrete logic implementations of MMC1 on development boards such as the MMC MULTI CHECKER-02, which uses separate shift registers for each MMC1 register.<ref>[https://forums.nesdev.org/viewtopic.php?t=25065 Forum thread:] MMC MULTI CHECKER-02 development board</ref><br />
<br />
=== Consecutive-cycle writes ===<br />
----<br />
When the serial port is written to on consecutive cycles, it ignores every write after the first. In practice, this only happens when the CPU executes read-modify-write instructions, which first write the original value before writing the modified one on the next cycle.<ref>[http://nesdev.org/6502_cpu.txt 6502_cpu.txt]. See the section labelled Instruction Timing, subsections Absolute addressing, Read-Modify-Write instructions</ref> This restriction only applies to the data being written on bit 0; the bit 7 reset is never ignored. ''Bill & Ted's Excellent Adventure'' does a reset by using INC on a ROM location containing $FF and requires that the $00 write on the next cycle is ignored. ''Shinsenden'', however, uses illegal instruction $7F (RRA abs,X) to set bit 7 on the second write and will crash after selecting the みる (look) option if this reset is ignored.<ref>[https://forums.nesdev.org/viewtopic.php?t=23730 Forum thread:] ''Shinsenden'' crash and MMC1 reset findings</ref> This write-ignore behavior appears to be intentional and is believed to ignore all consecutive write cycles after the first even if that first write does not target the serial port.<ref>[https://forums.nesdev.org/viewtopic.php?p=91562#p91562 Forum post:] MMC1 write investigation</ref><br />
<br />
== Registers ==<br />
=== Load register ($8000-$FFFF) ===<br />
7 bit 0<br />
---- ----<br />
Rxxx xxxD<br />
| |<br />
| +- Data bit to be shifted into shift register, LSB first<br />
+--------- A write with bit set will reset shift register<br />
and write Control with (Control OR $0C), <br />
locking PRG ROM at $C000-$FFFF to the last bank.<br />
<br />
On consecutive-cycle writes, writes to the shift register (D0) after the first are ignored. See [[#Consecutive-cycle_writes|Consecutive-cycle writes]] for more details.<br />
<br />
=== Control (internal, $8000-$9FFF) ===<br />
4bit0<br />
-----<br />
CPPMM<br />
|||||<br />
|||++- [[Mirroring]] (0: one-screen, lower bank; 1: one-screen, upper bank;<br />
||| 2: vertical; 3: horizontal)<br />
|++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;<br />
| 2: fix first bank at $8000 and switch 16 KB bank at $C000;<br />
| 3: fix last bank at $C000 and switch 16 KB bank at $8000)<br />
+----- CHR ROM bank mode (0: switch 8 KB at a time; 1: switch two separate 4 KB banks)<br />
<br />
Although [//forums.nesdev.org/viewtopic.php?t=6766 some tests have found that all versions of the MMC1 seems to reliably power on in the last bank] (by setting the "PRG ROM bank mode" to 3); [//forums.nesdev.org/viewtopic.php?f=2&t=14958 other tests have found that this is fragile]. Several commercial games have reset vectors every 32 KiB, but not every 16, so evidently PRG ROM bank mode 2 doesn't seem to occur randomly on power-up.<br />
<br />
=== CHR bank 0 (internal, $A000-$BFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB or 8 KB CHR bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
<br />
MMC1 can do CHR banking in 4KB chunks. Known carts with CHR RAM have 8 KiB, so that makes 2 banks. RAM vs ROM doesn't make any difference for address lines. For carts with 8 KiB of CHR (be it ROM or RAM), MMC1 follows the common behavior of using only the low-order bits: the bank number is in effect ANDed with 1.<br />
<br />
=== CHR bank 1 (internal, $C000-$DFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB CHR bank at PPU $1000 (ignored in 8 KB mode)<br />
<br />
=== PRG bank (internal, $E000-$FFFF) ===<br />
4bit0<br />
-----<br />
RPPPP<br />
|||||<br />
|++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode)<br />
+----- MMC1B and later: PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A)<br />
MMC1A: Bit 3 bypasses fixed bank logic in 16K mode (0: affected; 1: bypassed)<br />
<br />
The high bit does not select a PRG ROM bank. MMC1 with 512K was supported by re-using a line from the CHR banking controls. (See [[#SOROM, SUROM and SXROM|below]].)<br />
<br />
== Hardware ==<br />
<br />
At least six different versions of the MMC1 are known to exist: MMC1, MMC1A, MMC1B1, MMC1B2, MMC1B2F, MMC1B3. Additionally, there is one unsubstantiated report about an MMC1C. The known differences relate to bit 4 of $E000.<br />
<br />
* MMC1A: PRG RAM is always enabled. Two games abuse this lack of feature: they have been allocated to [[iNES Mapper 155]]. Bit 4 of $E000 causes bit 3 to directly control PRG ROM A17 instead of going through the fixed bank logic.<br />
* MMC1B: PRG RAM is enabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
* MMC1C: PRG RAM is (reportedly) disabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
<br />
The MMC1 most commonly exists in a [[MMC1 pinout|24-pin shrink-DIP package]]. An SOIC-24 incarnation MMC1B2F has been observed inside of a JRA-PAT Famicom Network System card.<br />
<br />
Boards using an MMC1 may contain a battery connected to the PRG RAM's power line to preserve the data.<br />
Boards doing so will allow extra circuitry to be used, with 2 diodes and 2 resistors.<br />
A diode is needed from both voltage sources: The battery and the NES 5V, so that one cannot supply current to the other, and there is a resistor in series with the battery as part of UL compliance. A pull-down resistor is needed on the CE line so that the SRAM is disabled when the MMC1 isn't powered. Finally, the battery powered SRAMs have an additional larger decoupling capacitor to make sure voltage transitions are smooth. Very early NES-SNROM-03 and lower revisions lacks that capcity, and saves are lost much more easily on those boards.<br />
<br />
Nintendo transitioned from the original MMC1 (manufactured by ROHM) to the MMC1A (manufactured probably by Ricoh) around the 39th week of 1988. (Based on comparison of otherwise identical SMB/DH/WCTM carts from 38th and 39th weeks of '88)<br />
<br />
AX5904 is a third-party clone of the MMC1A.<br />
<br />
== Variants ==<br />
<br />
Because the higher CHR lines aren't used when the MMC1 mapper is used with a 8KB CHR RAM, those lines are sometimes put to other uses depending on the board:<br />
<br />
=== SNROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus)<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus) (ignored in 8 KB mode)<br />
<br />
Both the <code>E</code> bit and the <code>R</code> bit (in standard MMC1 registers) should be clear in order for the PRG RAM to be writable or readable. This bit is more "reliable" on authentic hardware as it is implemented even in older boards with older MMC1's, while the <code>R</code> bit was only introduced later.<br />
But because the <code>E</code> bit wasn't confirmed by the homebrew community until October 2010<ref>[http://forums.nesdev.org/viewtopic.php?t=7045 Forum topic:] NES SNROM to 512K cart?</ref>, emulators tend not to implement it.<br />
<br />
=== SOROM, SUROM and SXROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank<br />
+----- Select 256 KB PRG ROM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
+----- Select 256 KB PRG ROM bank (ignored in 8 KB mode)<br />
<br />
The SOROM board only implements the upper <code>S</code> bit, while the SUROM board only implements the <code>P</code> bit. For SXROM, the upper <code>S</code> (bit 3) selects the SRAM's A14, and the lower <code>S</code> (bit 2) selects A13<ref>[http://forums.nesdev.org/viewtopic.php?t=4596 Forum post:] Tracing the SXROM PCB</ref>.<br />
<br />
The 256 KB PRG bank selection applies to all the PRG area, ''including the supposedly "fixed" bank''.<br />
<br />
In 4KB CHR bank mode, SNROM's <code>E</code> bit and SO/U/XROM's <code>P</code> and <code>S</code> bits in both CHR bank registers must be set to the same values, or the PRG ROM and/or RAM will be bankswitched/enabled as the PPU renders, in a similar fashion as [[MMC3#Hardware|MMC3]]'s scanline counter. As there is not much of a reason to use 4 KB bankswitching with CHR RAM, it is wise for programs to just set 8 KB bankswitching mode in the [[MMC1#Control (internal, $8000-$9FFF)|Control register]].<br />
<br />
=== SZROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
<br />
SZROM behaves similarly to SOROM, except that the PRG RAM bank is a controlled by a different bit, and enough CHR is present that 4K bankswitching is desirable. The only currently-known game on SZROM is ''A Ressha de Ikou''.<br />
<br />
SZROM can be detected by a NES2.0 header specifying 8K of PRG RAM, 8K of PRG NV RAM, and 16K or more of CHR.<br />
<br />
=== 2ME ===<br />
----<br />
This board, used with the [[Famicom Network System]] (FCNS), features 64 big-endian 16-bit words of EEPROM in addition to up to 32 KB of battery-backed PRG-RAM. Because FCNS cartridges are not on the PPU bus, all PPU-related MMC1 outputs are repurposed for EEPROM and PRG-RAM storage. The EEPROM's data output is mapped to $6000-7FFF bit 0 when enabled, and its command and data interface can be found in the 93LC46 datasheet. Note that open bus for this board is card open bus, which is open bus on the card side of the FCNS, not the console side.<br />
<br />
2ME is assigned [[NES_2.0_submappers#001:_MMC1|NES 2.0 MMC1 submapper 6]] and uses an MMC1B.<br />
<br />
==== Control (internal, $8000-9FFF) ====<br />
7 bit 0<br />
---- ----<br />
...I PPEE<br />
| ||||<br />
| ||++- EEPROM CS (01 = enabled, otherwise disabled)<br />
| ++--- PRG ROM bank mode (see [[MMC1#Control_(internal,_$8000-$9FFF)|standard register definition]])<br />
+------ EEPROM DI enable (0 = DI forced to 0, 1 = DI output enabled)<br />
<br />
The graphics-related bits here are repurposed for EEPROM enables. Because the MMC1's PPU A12-10 inputs are grounded on the 2ME board, settings that would normally vary based on PPU fetches such as the nametable arrangement and active CHR register are instead fixed.<br />
* The CIRAM A10 output is used as the EEPROM's CS input and will be always true in upper-bank single screen arrangement and always false otherwise.<br />
* The lowest CHR register bit is used for the EEPROM's DI input, but can only be non-zero in 4 KB banking mode. The second CHR register ($C000-DFFF) is unused in this mode because the PPU inputs are fixed such that they'll never point into the upper half of the pattern table space.<br />
<br />
==== CHR bank 0 (internal, $A000-BFFF) ====<br />
7 bit 0<br />
---- ----<br />
...O RRCI<br />
| ||||<br />
| |||+- EEPROM DI<br />
| ||+-- EEPROM CLK<br />
| |+--- PRG-RAM A13<br />
| +---- PRG-RAM A14<br />
+------ PRG-RAM /CE, and EEPROM DO +OE (0 = PRG-RAM enabled, 1 = EEPROM DO enabled)<br />
<br />
* EEPROM DI allows sending commands or data to the EEPROM. It is forced to 0 if 4 KB banking is not enabled via $8000 bit 4.<br />
* EEPROM CLK is used to transition to the next bit when reading from or writing to the EEPROM.<br />
* PRG-RAM banking uses the same bit order as SXROM.<br />
* The PRG-RAM /CE and EEPROM DO +OE bit acts as a selector for $6000-7FFF between PRG-RAM access and EEPROM read. The PRG-RAM enable matches the behavior of SNROM. While EEPROM is selected, bits 7-1 always return card open bus and bit 0 returns any data currently outputted by the EEPROM or card open bus otherwise.<br />
<br />
==== PRG bank (internal, $E000-FFFF) ====<br />
7 bit 0<br />
---- ----<br />
...D PPPP<br />
| ||||<br />
| ++++- PRG ROM bank (see [[MMC1#PRG_bank_(internal,_$E000-$FFFF)|standard register definition]])<br />
+------ $6000-7FFF disable (0 = enabled, 1 = disabled)<br />
<br />
If $6000-7FFF is disabled, then neither PRG-RAM nor EEPROM can be accessed through this region and reads return card open bus. EEPROM can still be written, however, because the DI input does not use this region.<br />
<br />
== iNES Mapper 001 ==<br />
<br />
'''iNES Mapper 001''' is used to designate the [[SxROM]] boardset, all of which use Nintendo's '''MMC1'''.<br />
<br />
Because some MMC1 boards (e.g. SOROM, SUROM and SXROM) used the upper CHR bank select lines instead to select additional PRG ROM or PRG RAM data, these bits should be assigned as follows:<br />
<br />
$A000 and $C000:<br />
4bit0<br />
-----<br />
EDCBA<br />
|||||<br />
||||+- CHR A12<br />
|||+-- CHR A13 if CHR >= 16k<br />
||+--- CHR A14 if CHR >= 32k; and PRG RAM A13 if PRG RAM = 32k<br />
|+---- CHR A15 if CHR >= 64k; and PRG RAM A13 if PRG RAM = 16k<br />
| or PRG RAM A14 if PRG RAM = 32k<br />
+----- CHR A16 if CHR = 128k; and PRG ROM A18 if PRG ROM = 512k<br />
<br />
The <code>E</code> bit also acts as a PRG RAM disable for SNROM (PRG ROM <= 256k, CHR RAM = 8k, PRG RAM = 8k), though this is merely for write protection and not strictly required for compatible emulation.<br />
<br />
The <code>D</code> bit used by SOROM (16k PRG RAM) and SXROM (32k PRG RAM) controls a different address line depending on the board type. Using A13 for <code>D</code> with both boards and A14 for <code>C</code> will work, but will break SXROM save file compatibility with correct implementations.<br />
<br />
[[NES 2.0]] is required to specify PRG-RAM size. Without NES 2.0 the PRG-RAM size has to be assumed (32k may be sufficient for compatibility).<br />
<br />
Boards designed for 32k PRG-ROM (SEROM, SHROM, and SH1ROM) do not connect PRG A14 to the MMC1, disabling PRG banking. For compatibility with these, the emulator may switch to PRG bank 0 at power-on. SIROM supports banked 32k PRG, however.<br />
<br />
== References ==<br />
<References/><br />
<br />
== See also ==<br />
*[[Programming MMC1]]<br />
*[[MMC1 pinout]]<br />
*[http://nesdev.org/mmc1.txt "Nintendo MMC1 info for 8-bit NES carts" by Matthew J. Richey]<br />
*[http://kevtris.org/mappers/mmc1/index.html MMC1 doc by Kevin Horton]<br />
*[http://nesdev.org/mappers.zip Comprehensive NES Mapper Document] by \Firebug\, information on SUROM/SXROM carts (512k carts, 1024k carts) is inaccurate<br />
* US Patent 4,949,298<br />
<br />
[[Category:Mappers with large PRG RAM]][[Category:Mappers with single-screen mirroring]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=MMC1&diff=21577MMC12024-01-25T14:33:43Z<p>Fiskbit: /* Reset */ Wording.</p>
<hr />
<div>{{Infobox iNES mapper<br />
|name=MMC1<br />
|name2=SxROM<br />
|company=Nintendo, others<br />
|mapper=1<br />
|nescartdbgames=390<br />
|othermappers=[[iNES Mapper 105|105]], [[iNES Mapper 155|155]]<br />
|complexity=ASIC<br />
|boards=SKROM, SLROM,<br/>SNROM, others<br />
|pinout=MMC1 pinout<br />
|prgmax=256K (512K)<br />
|prgpage=16K + 16K fixed or 32K<br />
|wrammax=32K<br />
|wrampage=8K<br />
|chrmax=128K<br />
|chrpage=4K + 4K or 8K<br />
|mirroring=H, V, or 1, switchable<br />
|busconflicts=No<br />
}}<br />
[[Category:Nintendo licensed mappers]][[Category:NES 2.0 mappers with submappers]]<br />
The '''Nintendo MMC1''' is a [[MMC|mapper]] [[:Category:ASIC mappers|ASIC]] used in Nintendo's [[SxROM]] and [[NES-EVENT]] Game Pak boards. Most common SxROM boards are assigned to '''iNES Mapper 1'''. This chip first appeared in the April of 1987.<br />
<br />
== Banks ==<br />
* CPU $6000-$7FFF: 8 KB PRG RAM bank, (optional)<br />
* CPU $8000-$BFFF: 16 KB PRG ROM bank, either switchable or fixed to the first bank<br />
* CPU $C000-$FFFF: 16 KB PRG ROM bank, either fixed to the last bank or switchable<br />
* PPU $0000-$0FFF: 4 KB switchable CHR bank<br />
* PPU $1000-$1FFF: 4 KB switchable CHR bank<br />
<br />
Through writes to the MMC1 control register, it is possible for the program to swap the fixed and switchable PRG ROM banks or to set up 32 KB PRG bankswitching (like [[BNROM]]), but most games use the default setup, which is similar to that of [[UxROM]].<br />
<br />
== Interface ==<br />
Unlike almost all other mappers, the MMC1 is configured through a serial port in order to reduce its pin count. CPU $8000-$FFFF is connected to a common shift register.<br />
Writing a value with bit 7 set ($80 through $FF) to any address in $8000-$FFFF clears the shift register to its initial state.<br />
To change a register's value, the CPU writes five times with bit 7 clear and one bit of the desired value in bit 0 (starting with the low bit of the value).<br />
On the first four writes, the MMC1 shifts bit 0 into a shift register.<br />
On the fifth write, the MMC1 copies bit 0 and the shift register contents into an internal register selected by bits 14 and 13 of the address, and then it clears the shift register.<br />
Only on the fifth write does the address matter, and even then, only bits 14 and 13 of the address matter because the mapper doesn't see the lower address bits (similar to the mirroring seen with [[PPU registers]]). After the fifth write, the shift register is cleared automatically, so writing again with bit 7 set to clear the shift register is not needed.<br />
<br />
=== Examples ===<br />
----<br />
==== Shift register ====<br />
To switch a bank, a program will execute code similar to the following:<br />
<br />
<pre><br />
;<br />
; Sets the switchable PRG ROM bank to the value of A.<br />
;<br />
; A MMC1_SR MMC1_PB<br />
setPRGBank: ; 000edcba 10000 Start with an empty shift register (SR). The 1 is used<br />
sta $E000 ; 000edcba -> a1000 to detect when the SR has become full.<br />
lsr a ; >0000edcb a1000<br />
sta $E000 ; 0000edcb -> ba100<br />
lsr a ; >00000edc ba100<br />
sta $E000 ; 00000edc -> cba10<br />
lsr a ; >000000ed cba10<br />
sta $E000 ; 000000ed -> dcba1 Once a 1 is shifted into the last position, the SR is full.<br />
lsr a ; >0000000e dcba1 <br />
sta $E000 ; 0000000e dcba1 -> edcba A write with the SR full copies D0 and the SR to a bank register<br />
; 10000 ($E000-$FFFF means PRG bank number) and then clears the SR.<br />
rts<br />
</pre><br />
<br />
But because only the fifth write sets the destination register, the following equivalent (if [[Watermarking#Instruction encoding|obfuscated]]) subroutine changes the PRG ROM bank in the same manner:<br />
<br />
<pre><br />
setPRGBank:<br />
sta $8765<br />
lsr a<br />
sta $FACE<br />
lsr a<br />
sta $BA11<br />
lsr a<br />
sta $AD2E<br />
lsr a<br />
sta $EAD5<br />
rts<br />
</pre><br />
<br />
==== Reset ====<br />
To reset the mapper, which clears the shift register and sets the PRG ROM bank mode to 3 (fixing the last bank at $C000 and allowing the 16 KB bank at $8000 to be switched), one need only do a single write to any ROM address with a 1 in bit 7:<br />
<br />
<pre><br />
resetMapper:<br />
lda #$80<br />
sta $8000<br />
rts<br />
</pre><br />
<br />
Commonly, reset is done with an increment on a negative value to save 2 bytes. Because increment performs two writes, first writing the old value before the incremented one, it is recommended (such as for wider emulator compatibility) that the increment target a value that is negative on both writes, such as the INC opcode ($EE) itself:<br />
<br />
<pre><br />
resetMapper:<br />
inc resetMapper<br />
rts<br />
</pre><br />
<br />
Note that some games do a reset write to each of the 4 registers, even though it is only necessary to do 1 reset write to any register. It is suspected these games do this because of discrete logic implementations of MMC1 on development boards such as the MMC MULTI CHECKER-02, which uses separate shift registers for each MMC1 register.<br />
<br />
=== Consecutive-cycle writes ===<br />
----<br />
When the serial port is written to on consecutive cycles, it ignores every write after the first. In practice, this only happens when the CPU executes read-modify-write instructions, which first write the original value before writing the modified one on the next cycle.<ref>[http://nesdev.org/6502_cpu.txt 6502_cpu.txt]. See the section labelled Instruction Timing, subsections Absolute addressing, Read-Modify-Write instructions</ref> This restriction only applies to the data being written on bit 0; the bit 7 reset is never ignored. ''Bill & Ted's Excellent Adventure'' does a reset by using INC on a ROM location containing $FF and requires that the $00 write on the next cycle is ignored. ''Shinsenden'', however, uses illegal instruction $7F (RRA abs,X) to set bit 7 on the second write and will crash after selecting the みる (look) option if this reset is ignored.<ref>[https://forums.nesdev.org/viewtopic.php?t=23730 Forum thread:] ''Shinsenden'' crash and MMC1 reset findings</ref> This write-ignore behavior appears to be intentional and is believed to ignore all consecutive write cycles after the first even if that first write does not target the serial port.<ref>[https://forums.nesdev.org/viewtopic.php?p=91562#p91562 Forum post:] MMC1 write investigation</ref><br />
<br />
== Registers ==<br />
=== Load register ($8000-$FFFF) ===<br />
7 bit 0<br />
---- ----<br />
Rxxx xxxD<br />
| |<br />
| +- Data bit to be shifted into shift register, LSB first<br />
+--------- A write with bit set will reset shift register<br />
and write Control with (Control OR $0C), <br />
locking PRG ROM at $C000-$FFFF to the last bank.<br />
<br />
On consecutive-cycle writes, writes to the shift register (D0) after the first are ignored. See [[#Consecutive-cycle_writes|Consecutive-cycle writes]] for more details.<br />
<br />
=== Control (internal, $8000-$9FFF) ===<br />
4bit0<br />
-----<br />
CPPMM<br />
|||||<br />
|||++- [[Mirroring]] (0: one-screen, lower bank; 1: one-screen, upper bank;<br />
||| 2: vertical; 3: horizontal)<br />
|++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;<br />
| 2: fix first bank at $8000 and switch 16 KB bank at $C000;<br />
| 3: fix last bank at $C000 and switch 16 KB bank at $8000)<br />
+----- CHR ROM bank mode (0: switch 8 KB at a time; 1: switch two separate 4 KB banks)<br />
<br />
Although [//forums.nesdev.org/viewtopic.php?t=6766 some tests have found that all versions of the MMC1 seems to reliably power on in the last bank] (by setting the "PRG ROM bank mode" to 3); [//forums.nesdev.org/viewtopic.php?f=2&t=14958 other tests have found that this is fragile]. Several commercial games have reset vectors every 32 KiB, but not every 16, so evidently PRG ROM bank mode 2 doesn't seem to occur randomly on power-up.<br />
<br />
=== CHR bank 0 (internal, $A000-$BFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB or 8 KB CHR bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
<br />
MMC1 can do CHR banking in 4KB chunks. Known carts with CHR RAM have 8 KiB, so that makes 2 banks. RAM vs ROM doesn't make any difference for address lines. For carts with 8 KiB of CHR (be it ROM or RAM), MMC1 follows the common behavior of using only the low-order bits: the bank number is in effect ANDed with 1.<br />
<br />
=== CHR bank 1 (internal, $C000-$DFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB CHR bank at PPU $1000 (ignored in 8 KB mode)<br />
<br />
=== PRG bank (internal, $E000-$FFFF) ===<br />
4bit0<br />
-----<br />
RPPPP<br />
|||||<br />
|++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode)<br />
+----- MMC1B and later: PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A)<br />
MMC1A: Bit 3 bypasses fixed bank logic in 16K mode (0: affected; 1: bypassed)<br />
<br />
The high bit does not select a PRG ROM bank. MMC1 with 512K was supported by re-using a line from the CHR banking controls. (See [[#SOROM, SUROM and SXROM|below]].)<br />
<br />
== Hardware ==<br />
<br />
At least six different versions of the MMC1 are known to exist: MMC1, MMC1A, MMC1B1, MMC1B2, MMC1B2F, MMC1B3. Additionally, there is one unsubstantiated report about an MMC1C. The known differences relate to bit 4 of $E000.<br />
<br />
* MMC1A: PRG RAM is always enabled. Two games abuse this lack of feature: they have been allocated to [[iNES Mapper 155]]. Bit 4 of $E000 causes bit 3 to directly control PRG ROM A17 instead of going through the fixed bank logic.<br />
* MMC1B: PRG RAM is enabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
* MMC1C: PRG RAM is (reportedly) disabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
<br />
The MMC1 most commonly exists in a [[MMC1 pinout|24-pin shrink-DIP package]]. An SOIC-24 incarnation MMC1B2F has been observed inside of a JRA-PAT Famicom Network System card.<br />
<br />
Boards using an MMC1 may contain a battery connected to the PRG RAM's power line to preserve the data.<br />
Boards doing so will allow extra circuitry to be used, with 2 diodes and 2 resistors.<br />
A diode is needed from both voltage sources: The battery and the NES 5V, so that one cannot supply current to the other, and there is a resistor in series with the battery as part of UL compliance. A pull-down resistor is needed on the CE line so that the SRAM is disabled when the MMC1 isn't powered. Finally, the battery powered SRAMs have an additional larger decoupling capacitor to make sure voltage transitions are smooth. Very early NES-SNROM-03 and lower revisions lacks that capcity, and saves are lost much more easily on those boards.<br />
<br />
Nintendo transitioned from the original MMC1 (manufactured by ROHM) to the MMC1A (manufactured probably by Ricoh) around the 39th week of 1988. (Based on comparison of otherwise identical SMB/DH/WCTM carts from 38th and 39th weeks of '88)<br />
<br />
AX5904 is a third-party clone of the MMC1A.<br />
<br />
== Variants ==<br />
<br />
Because the higher CHR lines aren't used when the MMC1 mapper is used with a 8KB CHR RAM, those lines are sometimes put to other uses depending on the board:<br />
<br />
=== SNROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus)<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus) (ignored in 8 KB mode)<br />
<br />
Both the <code>E</code> bit and the <code>R</code> bit (in standard MMC1 registers) should be clear in order for the PRG RAM to be writable or readable. This bit is more "reliable" on authentic hardware as it is implemented even in older boards with older MMC1's, while the <code>R</code> bit was only introduced later.<br />
But because the <code>E</code> bit wasn't confirmed by the homebrew community until October 2010<ref>[http://forums.nesdev.org/viewtopic.php?t=7045 Forum topic:] NES SNROM to 512K cart?</ref>, emulators tend not to implement it.<br />
<br />
=== SOROM, SUROM and SXROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank<br />
+----- Select 256 KB PRG ROM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
+----- Select 256 KB PRG ROM bank (ignored in 8 KB mode)<br />
<br />
The SOROM board only implements the upper <code>S</code> bit, while the SUROM board only implements the <code>P</code> bit. For SXROM, the upper <code>S</code> (bit 3) selects the SRAM's A14, and the lower <code>S</code> (bit 2) selects A13<ref>[http://forums.nesdev.org/viewtopic.php?t=4596 Forum post:] Tracing the SXROM PCB</ref>.<br />
<br />
The 256 KB PRG bank selection applies to all the PRG area, ''including the supposedly "fixed" bank''.<br />
<br />
In 4KB CHR bank mode, SNROM's <code>E</code> bit and SO/U/XROM's <code>P</code> and <code>S</code> bits in both CHR bank registers must be set to the same values, or the PRG ROM and/or RAM will be bankswitched/enabled as the PPU renders, in a similar fashion as [[MMC3#Hardware|MMC3]]'s scanline counter. As there is not much of a reason to use 4 KB bankswitching with CHR RAM, it is wise for programs to just set 8 KB bankswitching mode in the [[MMC1#Control (internal, $8000-$9FFF)|Control register]].<br />
<br />
=== SZROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
<br />
SZROM behaves similarly to SOROM, except that the PRG RAM bank is a controlled by a different bit, and enough CHR is present that 4K bankswitching is desirable. The only currently-known game on SZROM is ''A Ressha de Ikou''.<br />
<br />
SZROM can be detected by a NES2.0 header specifying 8K of PRG RAM, 8K of PRG NV RAM, and 16K or more of CHR.<br />
<br />
=== 2ME ===<br />
----<br />
This board, used with the [[Famicom Network System]] (FCNS), features 64 big-endian 16-bit words of EEPROM in addition to up to 32 KB of battery-backed PRG-RAM. Because FCNS cartridges are not on the PPU bus, all PPU-related MMC1 outputs are repurposed for EEPROM and PRG-RAM storage. The EEPROM's data output is mapped to $6000-7FFF bit 0 when enabled, and its command and data interface can be found in the 93LC46 datasheet. Note that open bus for this board is card open bus, which is open bus on the card side of the FCNS, not the console side.<br />
<br />
2ME is assigned [[NES_2.0_submappers#001:_MMC1|NES 2.0 MMC1 submapper 6]] and uses an MMC1B.<br />
<br />
==== Control (internal, $8000-9FFF) ====<br />
7 bit 0<br />
---- ----<br />
...I PPEE<br />
| ||||<br />
| ||++- EEPROM CS (01 = enabled, otherwise disabled)<br />
| ++--- PRG ROM bank mode (see [[MMC1#Control_(internal,_$8000-$9FFF)|standard register definition]])<br />
+------ EEPROM DI enable (0 = DI forced to 0, 1 = DI output enabled)<br />
<br />
The graphics-related bits here are repurposed for EEPROM enables. Because the MMC1's PPU A12-10 inputs are grounded on the 2ME board, settings that would normally vary based on PPU fetches such as the nametable arrangement and active CHR register are instead fixed.<br />
* The CIRAM A10 output is used as the EEPROM's CS input and will be always true in upper-bank single screen arrangement and always false otherwise.<br />
* The lowest CHR register bit is used for the EEPROM's DI input, but can only be non-zero in 4 KB banking mode. The second CHR register ($C000-DFFF) is unused in this mode because the PPU inputs are fixed such that they'll never point into the upper half of the pattern table space.<br />
<br />
==== CHR bank 0 (internal, $A000-BFFF) ====<br />
7 bit 0<br />
---- ----<br />
...O RRCI<br />
| ||||<br />
| |||+- EEPROM DI<br />
| ||+-- EEPROM CLK<br />
| |+--- PRG-RAM A13<br />
| +---- PRG-RAM A14<br />
+------ PRG-RAM /CE, and EEPROM DO +OE (0 = PRG-RAM enabled, 1 = EEPROM DO enabled)<br />
<br />
* EEPROM DI allows sending commands or data to the EEPROM. It is forced to 0 if 4 KB banking is not enabled via $8000 bit 4.<br />
* EEPROM CLK is used to transition to the next bit when reading from or writing to the EEPROM.<br />
* PRG-RAM banking uses the same bit order as SXROM.<br />
* The PRG-RAM /CE and EEPROM DO +OE bit acts as a selector for $6000-7FFF between PRG-RAM access and EEPROM read. The PRG-RAM enable matches the behavior of SNROM. While EEPROM is selected, bits 7-1 always return card open bus and bit 0 returns any data currently outputted by the EEPROM or card open bus otherwise.<br />
<br />
==== PRG bank (internal, $E000-FFFF) ====<br />
7 bit 0<br />
---- ----<br />
...D PPPP<br />
| ||||<br />
| ++++- PRG ROM bank (see [[MMC1#PRG_bank_(internal,_$E000-$FFFF)|standard register definition]])<br />
+------ $6000-7FFF disable (0 = enabled, 1 = disabled)<br />
<br />
If $6000-7FFF is disabled, then neither PRG-RAM nor EEPROM can be accessed through this region and reads return card open bus. EEPROM can still be written, however, because the DI input does not use this region.<br />
<br />
== iNES Mapper 001 ==<br />
<br />
'''iNES Mapper 001''' is used to designate the [[SxROM]] boardset, all of which use Nintendo's '''MMC1'''.<br />
<br />
Because some MMC1 boards (e.g. SOROM, SUROM and SXROM) used the upper CHR bank select lines instead to select additional PRG ROM or PRG RAM data, these bits should be assigned as follows:<br />
<br />
$A000 and $C000:<br />
4bit0<br />
-----<br />
EDCBA<br />
|||||<br />
||||+- CHR A12<br />
|||+-- CHR A13 if CHR >= 16k<br />
||+--- CHR A14 if CHR >= 32k; and PRG RAM A13 if PRG RAM = 32k<br />
|+---- CHR A15 if CHR >= 64k; and PRG RAM A13 if PRG RAM = 16k<br />
| or PRG RAM A14 if PRG RAM = 32k<br />
+----- CHR A16 if CHR = 128k; and PRG ROM A18 if PRG ROM = 512k<br />
<br />
The <code>E</code> bit also acts as a PRG RAM disable for SNROM (PRG ROM <= 256k, CHR RAM = 8k, PRG RAM = 8k), though this is merely for write protection and not strictly required for compatible emulation.<br />
<br />
The <code>D</code> bit used by SOROM (16k PRG RAM) and SXROM (32k PRG RAM) controls a different address line depending on the board type. Using A13 for <code>D</code> with both boards and A14 for <code>C</code> will work, but will break SXROM save file compatibility with correct implementations.<br />
<br />
[[NES 2.0]] is required to specify PRG-RAM size. Without NES 2.0 the PRG-RAM size has to be assumed (32k may be sufficient for compatibility).<br />
<br />
Boards designed for 32k PRG-ROM (SEROM, SHROM, and SH1ROM) do not connect PRG A14 to the MMC1, disabling PRG banking. For compatibility with these, the emulator may switch to PRG bank 0 at power-on. SIROM supports banked 32k PRG, however.<br />
<br />
== References ==<br />
<References/><br />
<br />
== See also ==<br />
*[[Programming MMC1]]<br />
*[[MMC1 pinout]]<br />
*[http://nesdev.org/mmc1.txt "Nintendo MMC1 info for 8-bit NES carts" by Matthew J. Richey]<br />
*[http://kevtris.org/mappers/mmc1/index.html MMC1 doc by Kevin Horton]<br />
*[http://nesdev.org/mappers.zip Comprehensive NES Mapper Document] by \Firebug\, information on SUROM/SXROM carts (512k carts, 1024k carts) is inaccurate<br />
* US Patent 4,949,298<br />
<br />
[[Category:Mappers with large PRG RAM]][[Category:Mappers with single-screen mirroring]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=MMC1&diff=21574MMC12024-01-25T11:42:08Z<p>Fiskbit: /* Reset */ Adds a note about why some games do reset writes to all 4 MMC1 registers.</p>
<hr />
<div>{{Infobox iNES mapper<br />
|name=MMC1<br />
|name2=SxROM<br />
|company=Nintendo, others<br />
|mapper=1<br />
|nescartdbgames=390<br />
|othermappers=[[iNES Mapper 105|105]], [[iNES Mapper 155|155]]<br />
|complexity=ASIC<br />
|boards=SKROM, SLROM,<br/>SNROM, others<br />
|pinout=MMC1 pinout<br />
|prgmax=256K (512K)<br />
|prgpage=16K + 16K fixed or 32K<br />
|wrammax=32K<br />
|wrampage=8K<br />
|chrmax=128K<br />
|chrpage=4K + 4K or 8K<br />
|mirroring=H, V, or 1, switchable<br />
|busconflicts=No<br />
}}<br />
[[Category:Nintendo licensed mappers]][[Category:NES 2.0 mappers with submappers]]<br />
The '''Nintendo MMC1''' is a [[MMC|mapper]] [[:Category:ASIC mappers|ASIC]] used in Nintendo's [[SxROM]] and [[NES-EVENT]] Game Pak boards. Most common SxROM boards are assigned to '''iNES Mapper 1'''. This chip first appeared in the April of 1987.<br />
<br />
== Banks ==<br />
* CPU $6000-$7FFF: 8 KB PRG RAM bank, (optional)<br />
* CPU $8000-$BFFF: 16 KB PRG ROM bank, either switchable or fixed to the first bank<br />
* CPU $C000-$FFFF: 16 KB PRG ROM bank, either fixed to the last bank or switchable<br />
* PPU $0000-$0FFF: 4 KB switchable CHR bank<br />
* PPU $1000-$1FFF: 4 KB switchable CHR bank<br />
<br />
Through writes to the MMC1 control register, it is possible for the program to swap the fixed and switchable PRG ROM banks or to set up 32 KB PRG bankswitching (like [[BNROM]]), but most games use the default setup, which is similar to that of [[UxROM]].<br />
<br />
== Interface ==<br />
Unlike almost all other mappers, the MMC1 is configured through a serial port in order to reduce its pin count. CPU $8000-$FFFF is connected to a common shift register.<br />
Writing a value with bit 7 set ($80 through $FF) to any address in $8000-$FFFF clears the shift register to its initial state.<br />
To change a register's value, the CPU writes five times with bit 7 clear and one bit of the desired value in bit 0 (starting with the low bit of the value).<br />
On the first four writes, the MMC1 shifts bit 0 into a shift register.<br />
On the fifth write, the MMC1 copies bit 0 and the shift register contents into an internal register selected by bits 14 and 13 of the address, and then it clears the shift register.<br />
Only on the fifth write does the address matter, and even then, only bits 14 and 13 of the address matter because the mapper doesn't see the lower address bits (similar to the mirroring seen with [[PPU registers]]). After the fifth write, the shift register is cleared automatically, so writing again with bit 7 set to clear the shift register is not needed.<br />
<br />
=== Examples ===<br />
----<br />
==== Shift register ====<br />
To switch a bank, a program will execute code similar to the following:<br />
<br />
<pre><br />
;<br />
; Sets the switchable PRG ROM bank to the value of A.<br />
;<br />
; A MMC1_SR MMC1_PB<br />
setPRGBank: ; 000edcba 10000 Start with an empty shift register (SR). The 1 is used<br />
sta $E000 ; 000edcba -> a1000 to detect when the SR has become full.<br />
lsr a ; >0000edcb a1000<br />
sta $E000 ; 0000edcb -> ba100<br />
lsr a ; >00000edc ba100<br />
sta $E000 ; 00000edc -> cba10<br />
lsr a ; >000000ed cba10<br />
sta $E000 ; 000000ed -> dcba1 Once a 1 is shifted into the last position, the SR is full.<br />
lsr a ; >0000000e dcba1 <br />
sta $E000 ; 0000000e dcba1 -> edcba A write with the SR full copies D0 and the SR to a bank register<br />
; 10000 ($E000-$FFFF means PRG bank number) and then clears the SR.<br />
rts<br />
</pre><br />
<br />
But because only the fifth write sets the destination register, the following equivalent (if [[Watermarking#Instruction encoding|obfuscated]]) subroutine changes the PRG ROM bank in the same manner:<br />
<br />
<pre><br />
setPRGBank:<br />
sta $8765<br />
lsr a<br />
sta $FACE<br />
lsr a<br />
sta $BA11<br />
lsr a<br />
sta $AD2E<br />
lsr a<br />
sta $EAD5<br />
rts<br />
</pre><br />
<br />
==== Reset ====<br />
To reset the mapper, which clears the shift register and sets the PRG ROM bank mode to 3 (fixing the last bank at $C000 and allowing the 16 KB bank at $8000 to be switched), one need only do a single write to any ROM address with a 1 in bit 7:<br />
<br />
<pre><br />
resetMapper:<br />
lda #$80<br />
sta $8000<br />
rts<br />
</pre><br />
<br />
Commonly, reset is done with an increment on a negative value to save 2 bytes. Because increment performs two writes, first writing the old value before the incremented one, it is recommended (such as for wider emulator compatibility) that the increment target a value that is negative on both writes, such as the INC opcode ($EE) itself:<br />
<br />
<pre><br />
resetMapper:<br />
inc resetMapper<br />
rts<br />
</pre><br />
<br />
Note that some games do a reset write to each of the 4 registers, but it is only necessary to do 1 reset write to any register. It is suspected these games do this because of discrete logic implementations of MMC1 on development boards such as the MMC MULTI CHECKER-02, which uses separate shift registers for each MMC1 register.<br />
<br />
=== Consecutive-cycle writes ===<br />
----<br />
When the serial port is written to on consecutive cycles, it ignores every write after the first. In practice, this only happens when the CPU executes read-modify-write instructions, which first write the original value before writing the modified one on the next cycle.<ref>[http://nesdev.org/6502_cpu.txt 6502_cpu.txt]. See the section labelled Instruction Timing, subsections Absolute addressing, Read-Modify-Write instructions</ref> This restriction only applies to the data being written on bit 0; the bit 7 reset is never ignored. ''Bill & Ted's Excellent Adventure'' does a reset by using INC on a ROM location containing $FF and requires that the $00 write on the next cycle is ignored. ''Shinsenden'', however, uses illegal instruction $7F (RRA abs,X) to set bit 7 on the second write and will crash after selecting the みる (look) option if this reset is ignored.<ref>[https://forums.nesdev.org/viewtopic.php?t=23730 Forum thread:] ''Shinsenden'' crash and MMC1 reset findings</ref> This write-ignore behavior appears to be intentional and is believed to ignore all consecutive write cycles after the first even if that first write does not target the serial port.<ref>[https://forums.nesdev.org/viewtopic.php?p=91562#p91562 Forum post:] MMC1 write investigation</ref><br />
<br />
== Registers ==<br />
=== Load register ($8000-$FFFF) ===<br />
7 bit 0<br />
---- ----<br />
Rxxx xxxD<br />
| |<br />
| +- Data bit to be shifted into shift register, LSB first<br />
+--------- A write with bit set will reset shift register<br />
and write Control with (Control OR $0C), <br />
locking PRG ROM at $C000-$FFFF to the last bank.<br />
<br />
On consecutive-cycle writes, writes to the shift register (D0) after the first are ignored. See [[#Consecutive-cycle_writes|Consecutive-cycle writes]] for more details.<br />
<br />
=== Control (internal, $8000-$9FFF) ===<br />
4bit0<br />
-----<br />
CPPMM<br />
|||||<br />
|||++- [[Mirroring]] (0: one-screen, lower bank; 1: one-screen, upper bank;<br />
||| 2: vertical; 3: horizontal)<br />
|++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;<br />
| 2: fix first bank at $8000 and switch 16 KB bank at $C000;<br />
| 3: fix last bank at $C000 and switch 16 KB bank at $8000)<br />
+----- CHR ROM bank mode (0: switch 8 KB at a time; 1: switch two separate 4 KB banks)<br />
<br />
Although [//forums.nesdev.org/viewtopic.php?t=6766 some tests have found that all versions of the MMC1 seems to reliably power on in the last bank] (by setting the "PRG ROM bank mode" to 3); [//forums.nesdev.org/viewtopic.php?f=2&t=14958 other tests have found that this is fragile]. Several commercial games have reset vectors every 32 KiB, but not every 16, so evidently PRG ROM bank mode 2 doesn't seem to occur randomly on power-up.<br />
<br />
=== CHR bank 0 (internal, $A000-$BFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB or 8 KB CHR bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
<br />
MMC1 can do CHR banking in 4KB chunks. Known carts with CHR RAM have 8 KiB, so that makes 2 banks. RAM vs ROM doesn't make any difference for address lines. For carts with 8 KiB of CHR (be it ROM or RAM), MMC1 follows the common behavior of using only the low-order bits: the bank number is in effect ANDed with 1.<br />
<br />
=== CHR bank 1 (internal, $C000-$DFFF) ===<br />
4bit0<br />
-----<br />
CCCCC<br />
|||||<br />
+++++- Select 4 KB CHR bank at PPU $1000 (ignored in 8 KB mode)<br />
<br />
=== PRG bank (internal, $E000-$FFFF) ===<br />
4bit0<br />
-----<br />
RPPPP<br />
|||||<br />
|++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode)<br />
+----- MMC1B and later: PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A)<br />
MMC1A: Bit 3 bypasses fixed bank logic in 16K mode (0: affected; 1: bypassed)<br />
<br />
The high bit does not select a PRG ROM bank. MMC1 with 512K was supported by re-using a line from the CHR banking controls. (See [[#SOROM, SUROM and SXROM|below]].)<br />
<br />
== Hardware ==<br />
<br />
At least six different versions of the MMC1 are known to exist: MMC1, MMC1A, MMC1B1, MMC1B2, MMC1B2F, MMC1B3. Additionally, there is one unsubstantiated report about an MMC1C. The known differences relate to bit 4 of $E000.<br />
<br />
* MMC1A: PRG RAM is always enabled. Two games abuse this lack of feature: they have been allocated to [[iNES Mapper 155]]. Bit 4 of $E000 causes bit 3 to directly control PRG ROM A17 instead of going through the fixed bank logic.<br />
* MMC1B: PRG RAM is enabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
* MMC1C: PRG RAM is (reportedly) disabled by default, and $E000 bit 3 does not bypass the fixed bank.<br />
<br />
The MMC1 most commonly exists in a [[MMC1 pinout|24-pin shrink-DIP package]]. An SOIC-24 incarnation MMC1B2F has been observed inside of a JRA-PAT Famicom Network System card.<br />
<br />
Boards using an MMC1 may contain a battery connected to the PRG RAM's power line to preserve the data.<br />
Boards doing so will allow extra circuitry to be used, with 2 diodes and 2 resistors.<br />
A diode is needed from both voltage sources: The battery and the NES 5V, so that one cannot supply current to the other, and there is a resistor in series with the battery as part of UL compliance. A pull-down resistor is needed on the CE line so that the SRAM is disabled when the MMC1 isn't powered. Finally, the battery powered SRAMs have an additional larger decoupling capacitor to make sure voltage transitions are smooth. Very early NES-SNROM-03 and lower revisions lacks that capcity, and saves are lost much more easily on those boards.<br />
<br />
Nintendo transitioned from the original MMC1 (manufactured by ROHM) to the MMC1A (manufactured probably by Ricoh) around the 39th week of 1988. (Based on comparison of otherwise identical SMB/DH/WCTM carts from 38th and 39th weeks of '88)<br />
<br />
AX5904 is a third-party clone of the MMC1A.<br />
<br />
== Variants ==<br />
<br />
Because the higher CHR lines aren't used when the MMC1 mapper is used with a 8KB CHR RAM, those lines are sometimes put to other uses depending on the board:<br />
<br />
=== SNROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus)<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
ExxxC<br />
| |<br />
| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- PRG RAM disable (0: enable, 1: open bus) (ignored in 8 KB mode)<br />
<br />
Both the <code>E</code> bit and the <code>R</code> bit (in standard MMC1 registers) should be clear in order for the PRG RAM to be writable or readable. This bit is more "reliable" on authentic hardware as it is implemented even in older boards with older MMC1's, while the <code>R</code> bit was only introduced later.<br />
But because the <code>E</code> bit wasn't confirmed by the homebrew community until October 2010<ref>[http://forums.nesdev.org/viewtopic.php?t=7045 Forum topic:] NES SNROM to 512K cart?</ref>, emulators tend not to implement it.<br />
<br />
=== SOROM, SUROM and SXROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $0000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank<br />
+----- Select 256 KB PRG ROM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
PSSxC<br />
||| |<br />
||| +- Select 4 KB CHR RAM bank at PPU $1000 (ignored in 8 KB mode)<br />
|++--- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
+----- Select 256 KB PRG ROM bank (ignored in 8 KB mode)<br />
<br />
The SOROM board only implements the upper <code>S</code> bit, while the SUROM board only implements the <code>P</code> bit. For SXROM, the upper <code>S</code> (bit 3) selects the SRAM's A14, and the lower <code>S</code> (bit 2) selects A13<ref>[http://forums.nesdev.org/viewtopic.php?t=4596 Forum post:] Tracing the SXROM PCB</ref>.<br />
<br />
The 256 KB PRG bank selection applies to all the PRG area, ''including the supposedly "fixed" bank''.<br />
<br />
In 4KB CHR bank mode, SNROM's <code>E</code> bit and SO/U/XROM's <code>P</code> and <code>S</code> bits in both CHR bank registers must be set to the same values, or the PRG ROM and/or RAM will be bankswitched/enabled as the PPU renders, in a similar fashion as [[MMC3#Hardware|MMC3]]'s scanline counter. As there is not much of a reason to use 4 KB bankswitching with CHR RAM, it is wise for programs to just set 8 KB bankswitching mode in the [[MMC1#Control (internal, $8000-$9FFF)|Control register]].<br />
<br />
=== SZROM ===<br />
----<br />
==== CHR bank 0 (internal, $A000-$BFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $0000 (low bit ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank<br />
<br />
==== CHR bank 1 (internal, $C000-$DFFF) ====<br />
4bit0<br />
-----<br />
RCCCC<br />
|||||<br />
|++++- Select 4 KB CHR ROM bank at PPU $1000 (ignored in 8 KB mode)<br />
+----- Select 8 KB PRG RAM bank (ignored in 8 KB mode)<br />
<br />
SZROM behaves similarly to SOROM, except that the PRG RAM bank is a controlled by a different bit, and enough CHR is present that 4K bankswitching is desirable. The only currently-known game on SZROM is ''A Ressha de Ikou''.<br />
<br />
SZROM can be detected by a NES2.0 header specifying 8K of PRG RAM, 8K of PRG NV RAM, and 16K or more of CHR.<br />
<br />
=== 2ME ===<br />
----<br />
This board, used with the [[Famicom Network System]] (FCNS), features 64 big-endian 16-bit words of EEPROM in addition to up to 32 KB of battery-backed PRG-RAM. Because FCNS cartridges are not on the PPU bus, all PPU-related MMC1 outputs are repurposed for EEPROM and PRG-RAM storage. The EEPROM's data output is mapped to $6000-7FFF bit 0 when enabled, and its command and data interface can be found in the 93LC46 datasheet. Note that open bus for this board is card open bus, which is open bus on the card side of the FCNS, not the console side.<br />
<br />
2ME is assigned [[NES_2.0_submappers#001:_MMC1|NES 2.0 MMC1 submapper 6]] and uses an MMC1B.<br />
<br />
==== Control (internal, $8000-9FFF) ====<br />
7 bit 0<br />
---- ----<br />
...I PPEE<br />
| ||||<br />
| ||++- EEPROM CS (01 = enabled, otherwise disabled)<br />
| ++--- PRG ROM bank mode (see [[MMC1#Control_(internal,_$8000-$9FFF)|standard register definition]])<br />
+------ EEPROM DI enable (0 = DI forced to 0, 1 = DI output enabled)<br />
<br />
The graphics-related bits here are repurposed for EEPROM enables. Because the MMC1's PPU A12-10 inputs are grounded on the 2ME board, settings that would normally vary based on PPU fetches such as the nametable arrangement and active CHR register are instead fixed.<br />
* The CIRAM A10 output is used as the EEPROM's CS input and will be always true in upper-bank single screen arrangement and always false otherwise.<br />
* The lowest CHR register bit is used for the EEPROM's DI input, but can only be non-zero in 4 KB banking mode. The second CHR register ($C000-DFFF) is unused in this mode because the PPU inputs are fixed such that they'll never point into the upper half of the pattern table space.<br />
<br />
==== CHR bank 0 (internal, $A000-BFFF) ====<br />
7 bit 0<br />
---- ----<br />
...O RRCI<br />
| ||||<br />
| |||+- EEPROM DI<br />
| ||+-- EEPROM CLK<br />
| |+--- PRG-RAM A13<br />
| +---- PRG-RAM A14<br />
+------ PRG-RAM /CE, and EEPROM DO +OE (0 = PRG-RAM enabled, 1 = EEPROM DO enabled)<br />
<br />
* EEPROM DI allows sending commands or data to the EEPROM. It is forced to 0 if 4 KB banking is not enabled via $8000 bit 4.<br />
* EEPROM CLK is used to transition to the next bit when reading from or writing to the EEPROM.<br />
* PRG-RAM banking uses the same bit order as SXROM.<br />
* The PRG-RAM /CE and EEPROM DO +OE bit acts as a selector for $6000-7FFF between PRG-RAM access and EEPROM read. The PRG-RAM enable matches the behavior of SNROM. While EEPROM is selected, bits 7-1 always return card open bus and bit 0 returns any data currently outputted by the EEPROM or card open bus otherwise.<br />
<br />
==== PRG bank (internal, $E000-FFFF) ====<br />
7 bit 0<br />
---- ----<br />
...D PPPP<br />
| ||||<br />
| ++++- PRG ROM bank (see [[MMC1#PRG_bank_(internal,_$E000-$FFFF)|standard register definition]])<br />
+------ $6000-7FFF disable (0 = enabled, 1 = disabled)<br />
<br />
If $6000-7FFF is disabled, then neither PRG-RAM nor EEPROM can be accessed through this region and reads return card open bus. EEPROM can still be written, however, because the DI input does not use this region.<br />
<br />
== iNES Mapper 001 ==<br />
<br />
'''iNES Mapper 001''' is used to designate the [[SxROM]] boardset, all of which use Nintendo's '''MMC1'''.<br />
<br />
Because some MMC1 boards (e.g. SOROM, SUROM and SXROM) used the upper CHR bank select lines instead to select additional PRG ROM or PRG RAM data, these bits should be assigned as follows:<br />
<br />
$A000 and $C000:<br />
4bit0<br />
-----<br />
EDCBA<br />
|||||<br />
||||+- CHR A12<br />
|||+-- CHR A13 if CHR >= 16k<br />
||+--- CHR A14 if CHR >= 32k; and PRG RAM A13 if PRG RAM = 32k<br />
|+---- CHR A15 if CHR >= 64k; and PRG RAM A13 if PRG RAM = 16k<br />
| or PRG RAM A14 if PRG RAM = 32k<br />
+----- CHR A16 if CHR = 128k; and PRG ROM A18 if PRG ROM = 512k<br />
<br />
The <code>E</code> bit also acts as a PRG RAM disable for SNROM (PRG ROM <= 256k, CHR RAM = 8k, PRG RAM = 8k), though this is merely for write protection and not strictly required for compatible emulation.<br />
<br />
The <code>D</code> bit used by SOROM (16k PRG RAM) and SXROM (32k PRG RAM) controls a different address line depending on the board type. Using A13 for <code>D</code> with both boards and A14 for <code>C</code> will work, but will break SXROM save file compatibility with correct implementations.<br />
<br />
[[NES 2.0]] is required to specify PRG-RAM size. Without NES 2.0 the PRG-RAM size has to be assumed (32k may be sufficient for compatibility).<br />
<br />
Boards designed for 32k PRG-ROM (SEROM, SHROM, and SH1ROM) do not connect PRG A14 to the MMC1, disabling PRG banking. For compatibility with these, the emulator may switch to PRG bank 0 at power-on. SIROM supports banked 32k PRG, however.<br />
<br />
== References ==<br />
<References/><br />
<br />
== See also ==<br />
*[[Programming MMC1]]<br />
*[[MMC1 pinout]]<br />
*[http://nesdev.org/mmc1.txt "Nintendo MMC1 info for 8-bit NES carts" by Matthew J. Richey]<br />
*[http://kevtris.org/mappers/mmc1/index.html MMC1 doc by Kevin Horton]<br />
*[http://nesdev.org/mappers.zip Comprehensive NES Mapper Document] by \Firebug\, information on SUROM/SXROM carts (512k carts, 1024k carts) is inaccurate<br />
* US Patent 4,949,298<br />
<br />
[[Category:Mappers with large PRG RAM]][[Category:Mappers with single-screen mirroring]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Input_devices&diff=21565Input devices2024-01-20T07:11:39Z<p>Fiskbit: /* Usage of port pins by hardware type */ Removes read clock signal from controllers that likely don't actually use it.</p>
<hr />
<div>The NES has two [[Controller port pinout|general-purpose controller ports]] on the front of the console, as well as a (rarely used) [[NES_expansion_port_pinout|48-pin expansion port]] underneath.<br />
<br />
The Famicom's standard controllers are hardwired to the front of the unit, and a special [[Famicom expansion port pinout|15-pin expansion port]] is commonly used for third-party controllers. The AV Famicom, however, features detachable controllers using the same ports as the NES.<br />
<br />
The NES and Famicom have a set of I/O ports used for controllers and other peripherals, consisting of the following:<br />
* One output port, 3 bits wide, accessible by writing the bottom 3 bits of $4016.<br />
** The values latched by $4016/write appear on the [[CPU_pin_out_and_signal_description|OUT0-OUT2]] output pins of the 2A03/07, where OUT0 is routed to the controller ports and OUT0-OUT2 to the expansion port on the NES.<br />
* Two input ports, each 5 bits wide, accessible by reading the bottom 5 bits of $4016 and $4017. Reading $4016 and $4017 activates the [[CPU_pin_out_and_signal_description|/OE1 and /OE2]] signals, respectively, which are routed to the controller ports and the expansion port.<br />
** On the NES, only D0, D3, and D4 are connected to both controller ports, while all of D0-D4 are connected to the expansion port. <br />
** On the original Famicom, the two ports differ: $4016 D0 and D2 and $4017 D0 are permanently connected to both controllers, while $4016 D1 and all of $4017's D0-D4 are connected to the expansion port.<br />
** On the AV Famicom, only D0 is connected to the controller ports. The expansion port is unchanged.<br />
== Programmer's reference ==<br />
* [[Controller reading]]<br />
<br />
== Hardware ==<br />
* [[Controller port pinout]]<br />
* Controllers<br />
** '''NES [[Standard controller]]'''<br />
** [[Arkanoid controller]]<br />
** [[Bandai Hyper Shot]]<br />
** [[Coconuts Pachinko]]<br />
** [[Doremikko Keyboard]]<br />
** [[Exciting Boxing Punching Bag]]<br />
** [[Family BASIC Keyboard]]<br />
** [[Four Score|Four Score, NES Satellite]] 4-player adapters<br />
** [[Hori 4 Players Adapter]] for Famicom<br />
** [[Jissen Mahjong controller]]<br />
** [[Konami Hyper Shot]]<br />
** [[Miracle Piano]]<br />
** [[Mouse]] (SNES Mouse, Subor Mouse)<br />
** [[Oeka Kids tablet]]<br />
** [[Partytap]]<br />
** [[Pokkun Moguraa Mat]]<br />
** [[Power Glove]]<br />
** [[Power Pad]]<br />
** [[RacerMate Bicycle]]<br />
** [[SNES controller]]<br />
** [[Top Rider Bike]]<br />
** [[U-Force]]<br />
** [[Virtual Boy controller]]<br />
** [[Zapper]] lightgun<br />
* [[Infrared controllers]]<br />
<br />
== Other I/O devices ==<br />
* [[Famicom 3D glasses]]<br />
* [[Family BASIC Data Recorder]]<br />
* [[R.O.B.]]<br />
* [[Battle Box]]<br />
* [[Turbo File]]<br />
* [[Barcode Battler]]<br />
* [[TV-NET Rank 2 controller]]<br />
* [[FAM-NET Keyboard]]<br />
* [[Family Computer Network Adapter]]<br />
* [[Super Famicom NTT Data Keypad]]<br />
<br />
== Usage of port pins by hardware type ==<br />
{| class="wikitable"<br />
|-<br />
|style="text-align: left;"|type<br />
!colspan="3" style="border-left: 2px solid black;"|output<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 1<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 2<br />
!style="border-left: 2px solid black;"|audio output<br />
|-<br />
|style="text-align: left;"|signal<br />
!style="border-left: 2px solid black;"|OUT2<br />
!OUT1<br />
!OUT0<br />
!style="border-left: 2px solid black;"|/OE1<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|/OE2<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|AUDIO<br />
|-<br />
|access method<br />
|colspan="3" style="text-align: center; border-left: 2px solid black;"|write $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE1 is activated by reading $4016.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE2 is activated by reading $4017.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4017<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|available on these ports<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|Controller port 1 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 1 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 1 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 2 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Expansion port#Famicom|Expansion port]] (Famicom)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Expansion port#NES|Expansion port]] (NES)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|used by these devices<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 1)<ref name="port">Controllers using NES ports can be plugged into either port, using that port's /OE and data lines. However, games may expect a controller to only be in a specific port.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (Famicom controller 2)<ref>The Famicom controller 2 has a microphone that sends audio input over $4016 D2. This is not affected by OUT0 nor /OE2.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<ref>A Famicom expansion controller may connect the audio output signal to a headphone jack (for example: IQ502 joypad).</ref><br />
|-<br />
|[[Arkanoid controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller#Arkanoid II expansion port|Arkanoid II controller]] (2 controllers)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Bandai Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
|<br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Exciting Boxing Punching Bag]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[FAM-NET Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Power Pad#Family Trainer Mat|Family Trainer Mat]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Family BASIC Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom 3D System]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom Network Controller|Famicom Network System controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|Four player adapter ([[Four Score]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Four player adapter ([[Four Score|Hori 4 Players Adapter]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2 <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Hori Track]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Jissen Mahjong controller]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Konami Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Oeka Kids tablet]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Coconuts Japan Pachinko Controller|Pachinko controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Party Tap]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Power Pad]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Port test controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|<br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[TV-NET controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[TV-NET Rank 2 controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Zapper]] (port 2)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Zapper]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|<ref>The Casel Zapper plays audio when the trigger is pulled, but this is done entirely by the controller independent of the console's audio out.</ref><br />
|-<br />
|[[Zapper]] (Vs. System) (port 1)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|<br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|}<br />
<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=Famicom_Network_Controller&diff=21564Famicom Network Controller2024-01-20T06:45:47Z<p>Fiskbit: Adds a controller image. Does some minor cleanup.</p>
<hr />
<div>[[Category:Controllers]]<br />
[[File:Nintendo-Famicom-Modem-Controller.jpg|400px|thumb|right|Famicom Network Controller]]<br />
The [[Famicom Network Controller]] (HVC-051) is a 23-button controller for use with the [[Famicom Network System]]. It is essentially a [[standard controller]] that adds a number pad, and can be used with normal games.<br />
<br />
==Layout==<br />
.------------------------------------------.<br />
| (<) (>) (1) (2) (3) (*) (C) |<br />
| SEL _ STA (END) |<br />
| _| |_ (4) (5) (6) (#) (.) |<br />
| |_ _| |<br />
| |_| (7) (8) (9) ( 0 ) (B) (A) |<br />
'------------------------------------------'<br />
(ASCII art courtesy Nocash)<br />
<br />
* The Select button has the additional text 前パージ = Previous Page<br />
* The Start button has the additional text 次パージ = Next Page<br />
* The B button has the additional text 目次 = Table of Contents<br />
* The A button has the additional text 実行 = Execute<br />
* The button marked "END" instead has the text 通信終了 = End of Communication<br />
<br />
==Protocol==<br />
<br />
The protocol looks like a standard Famicom [[expansion port]] controller, returning its result via reads from $4016 D1. After the initial eight reads, the following sixteen reads return the following bits in order:<br />
<br />
0-7 - see [[Standard controller]]<br />
8 - 0<br />
9 - 1<br />
10 - 2<br />
11 - 3<br />
12 - 4<br />
13 - 5<br />
14 - 6<br />
15 - 7<br />
16 - 8<br />
17 - 9<br />
18 - *<br />
19 - #<br />
20 - .<br />
21 - C<br />
22 - (Always 0)<br />
23 - 通信終了<br />
<br />
Like the standard controller, reads after the first 24 read as logic 1.<br />
<br />
==Sources==<br />
* [https://www.raphnet.net/divers/famicom_network_controller_hvc_051/index_en.php Raphnet]<br />
* [//forums.nesdev.org/viewtopic.php?p=247107#p247107 astro187 on the forum]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Nintendo-Famicom-Modem-Controller.jpg&diff=21563File:Nintendo-Famicom-Modem-Controller.jpg2024-01-20T06:38:03Z<p>Fiskbit: The Famicom Network Controller, for use with Famicom Network System software.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The Famicom Network Controller, for use with Famicom Network System software.<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Input_devices&diff=21562Input devices2024-01-20T05:24:07Z<p>Fiskbit: Fixes content accidentally removed in previous edit.</p>
<hr />
<div>The NES has two [[Controller port pinout|general-purpose controller ports]] on the front of the console, as well as a (rarely used) [[NES_expansion_port_pinout|48-pin expansion port]] underneath.<br />
<br />
The Famicom's standard controllers are hardwired to the front of the unit, and a special [[Famicom expansion port pinout|15-pin expansion port]] is commonly used for third-party controllers. The AV Famicom, however, features detachable controllers using the same ports as the NES.<br />
<br />
The NES and Famicom have a set of I/O ports used for controllers and other peripherals, consisting of the following:<br />
* One output port, 3 bits wide, accessible by writing the bottom 3 bits of $4016.<br />
** The values latched by $4016/write appear on the [[CPU_pin_out_and_signal_description|OUT0-OUT2]] output pins of the 2A03/07, where OUT0 is routed to the controller ports and OUT0-OUT2 to the expansion port on the NES.<br />
* Two input ports, each 5 bits wide, accessible by reading the bottom 5 bits of $4016 and $4017. Reading $4016 and $4017 activates the [[CPU_pin_out_and_signal_description|/OE1 and /OE2]] signals, respectively, which are routed to the controller ports and the expansion port.<br />
** On the NES, only D0, D3, and D4 are connected to both controller ports, while all of D0-D4 are connected to the expansion port. <br />
** On the original Famicom, the two ports differ: $4016 D0 and D2 and $4017 D0 are permanently connected to both controllers, while $4016 D1 and all of $4017's D0-D4 are connected to the expansion port.<br />
** On the AV Famicom, only D0 is connected to the controller ports. The expansion port is unchanged.<br />
== Programmer's reference ==<br />
* [[Controller reading]]<br />
<br />
== Hardware ==<br />
* [[Controller port pinout]]<br />
* Controllers<br />
** '''NES [[Standard controller]]'''<br />
** [[Arkanoid controller]]<br />
** [[Bandai Hyper Shot]]<br />
** [[Coconuts Pachinko]]<br />
** [[Doremikko Keyboard]]<br />
** [[Exciting Boxing Punching Bag]]<br />
** [[Family BASIC Keyboard]]<br />
** [[Four Score|Four Score, NES Satellite]] 4-player adapters<br />
** [[Hori 4 Players Adapter]] for Famicom<br />
** [[Jissen Mahjong controller]]<br />
** [[Konami Hyper Shot]]<br />
** [[Miracle Piano]]<br />
** [[Mouse]] (SNES Mouse, Subor Mouse)<br />
** [[Oeka Kids tablet]]<br />
** [[Partytap]]<br />
** [[Pokkun Moguraa Mat]]<br />
** [[Power Glove]]<br />
** [[Power Pad]]<br />
** [[RacerMate Bicycle]]<br />
** [[SNES controller]]<br />
** [[Top Rider Bike]]<br />
** [[U-Force]]<br />
** [[Virtual Boy controller]]<br />
** [[Zapper]] lightgun<br />
* [[Infrared controllers]]<br />
<br />
== Other I/O devices ==<br />
* [[Famicom 3D glasses]]<br />
* [[Family BASIC Data Recorder]]<br />
* [[R.O.B.]]<br />
* [[Battle Box]]<br />
* [[Turbo File]]<br />
* [[Barcode Battler]]<br />
* [[TV-NET Rank 2 controller]]<br />
* [[FAM-NET Keyboard]]<br />
* [[Family Computer Network Adapter]]<br />
* [[Super Famicom NTT Data Keypad]]<br />
<br />
== Usage of port pins by hardware type ==<br />
{| class="wikitable"<br />
|-<br />
|style="text-align: left;"|type<br />
!colspan="3" style="border-left: 2px solid black;"|output<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 1<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 2<br />
!style="border-left: 2px solid black;"|audio output<br />
|-<br />
|style="text-align: left;"|signal<br />
!style="border-left: 2px solid black;"|OUT2<br />
!OUT1<br />
!OUT0<br />
!style="border-left: 2px solid black;"|/OE1<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|/OE2<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|AUDIO<br />
|-<br />
|access method<br />
|colspan="3" style="text-align: center; border-left: 2px solid black;"|write $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE1 is activated by reading $4016.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE2 is activated by reading $4017.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4017<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|available on these ports<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|Controller port 1 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 1 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 1 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 2 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Expansion port#Famicom|Expansion port]] (Famicom)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Expansion port#NES|Expansion port]] (NES)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|used by these devices<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 1)<ref name="port">Controllers using NES ports can be plugged into either port, using that port's /OE and data lines. However, games may expect a controller to only be in a specific port.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (Famicom controller 2)<ref>The Famicom controller 2 has a microphone that sends audio input over $4016 D2. This is not affected by OUT0 nor /OE2.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<ref>A Famicom expansion controller may connect the audio output signal to a headphone jack (for example: IQ502 joypad).</ref><br />
|-<br />
|[[Arkanoid controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller#Arkanoid II expansion port|Arkanoid II controller]] (2 controllers)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Bandai Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
|<br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Exciting Boxing Punching Bag]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[FAM-NET Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Power Pad#Family Trainer Mat|Family Trainer Mat]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Family BASIC Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom 3D System]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom Network Controller|Famicom Network System controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|Four player adapter ([[Four Score]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Four player adapter ([[Four Score|Hori 4 Players Adapter]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2 <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Hori Track]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Jissen Mahjong controller]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Konami Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Oeka Kids tablet]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Coconuts Japan Pachinko Controller|Pachinko controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Party Tap]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Power Pad]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Port test controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|<br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[TV-NET controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[TV-NET Rank 2 controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Zapper]] (port 2)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Zapper]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|<ref>The Casel Zapper plays audio when the trigger is pulled, but this is done entirely by the controller independent of the console's audio out.</ref><br />
|-<br />
|[[Zapper]] (Vs. System) (port 1)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|<br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|}<br />
<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=Input_devices&diff=21561Input devices2024-01-20T05:22:48Z<p>Fiskbit: Reworks the signal table to be better organized and easier to read. Adds more devices. Fixes the zapper audio signal.</p>
<hr />
<div>== Usage of port pins by hardware type ==<br />
{| class="wikitable"<br />
|-<br />
|style="text-align: left;"|type<br />
!colspan="3" style="border-left: 2px solid black;"|output<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 1<br />
!colspan="6" style="border-left: 2px solid black;"|Joypad 2<br />
!style="border-left: 2px solid black;"|audio output<br />
|-<br />
|style="text-align: left;"|signal<br />
!style="border-left: 2px solid black;"|OUT2<br />
!OUT1<br />
!OUT0<br />
!style="border-left: 2px solid black;"|/OE1<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|/OE2<br />
!style="border-left: 2px solid gray;"|D4<br />
!D3<br />
!D2<br />
!D1<br />
!D0<br />
!style="border-left: 2px solid black;"|AUDIO<br />
|-<br />
|access method<br />
|colspan="3" style="text-align: center; border-left: 2px solid black;"|write $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE1 is activated by reading $4016.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4016<br />
|style="border-left: 2px solid black;"|<ref>/OE2 is activated by reading $4017.</ref><br />
|colspan="5" style="text-align: center; border-left: 2px solid gray;"|read $4017<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|available on these ports<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|Controller port 1 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 1 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 1 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (AV Famicom)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Controller port 2 (Famicom (internal))<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Controller port pinout|Controller port]] 2 (NES)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Expansion port#Famicom|Expansion port]] (Famicom)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Expansion port#NES|Expansion port]] (NES)<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
|D0<br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
!style="text-align: left; border-top: 2px solid black;"|used by these devices<br />
!colspan="3" style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
!colspan="5" style="border-left: 2px solid gray; border-top: 2px solid black;"| <br />
!style="border-left: 2px solid black; border-top: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 1)<ref name="port">Controllers using NES ports can be plugged into either port, using that port's /OE and data lines. However, games may expect a controller to only be in a specific port.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (Famicom controller 2)<ref>The Famicom controller 2 has a microphone that sends audio input over $4016 D2. This is not affected by OUT0 nor /OE2.</ref><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Standard controller|Controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<ref>A Famicom expansion controller may connect the audio output signal to a headphone jack (for example: IQ502 joypad).</ref><br />
|-<br />
|[[Arkanoid controller]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Arkanoid controller#Arkanoid II expansion port|Arkanoid II controller]] (2 controllers)<br />
|style="border-left: 2px solid black;"| <br />
|<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Bandai Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
|<br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|AUDIO<br />
|-<br />
|[[Exciting Boxing Punching Bag]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[FAM-NET Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Power Pad#Family Trainer Mat|Family Trainer Mat]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Family BASIC Keyboard]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom 3D System]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Famicom Network Controller|Famicom Network System controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|Four player adapter ([[Four Score]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|Four player adapter ([[Four Score|Hori 4 Players Adapter]])<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"|/OE2 <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Hori Track]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Jissen Mahjong controller]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Konami Hyper Shot]]<br />
|style="border-left: 2px solid black;"|OUT2<br />
|OUT1<br />
|<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
|<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Oeka Kids tablet]]<br />
|style="border-left: 2px solid black;"| <br />
|OUT1<br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Coconuts Japan Pachinko Controller|Pachinko controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Party Tap]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|D2<br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Power Pad]] (port 2)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Port test controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
|<br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|/OE2<br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
|<br />
|D0<br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[TV-NET controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[TV-NET Rank 2 controller]]<br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
|D1<br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"|<br />
|-<br />
|[[Zapper]] (port 2)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|-<br />
|[[Zapper]] (expansion port)<br />
|style="border-left: 2px solid black;"| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"| <br />
| <br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black;"| <br />
|style="border-left: 2px solid gray;"|D4<br />
|D3<br />
| <br />
| <br />
| <br />
|style="border-left: 2px solid black; text-align: center;"|<ref>The Casel Zapper plays audio when the trigger is pulled, but this is done entirely by the controller independent of the console's audio out.</ref><br />
|-<br />
|[[Zapper]] (Vs. System) (port 1)<ref name="port" /><br />
|style="border-left: 2px solid black;"| <br />
| <br />
|OUT0<br />
|style="border-left: 2px solid black;"|/OE1<br />
|style="border-left: 2px solid gray;"|<br />
| <br />
| <br />
| <br />
|D0<br />
|style="border-left: 2px solid black;"|<br />
|style="border-left: 2px solid gray;"|<br />
|<br />
| <br />
|<br />
| <br />
|style="border-left: 2px solid black;"|<br />
|}<br />
<br />
<references/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=Konami_Hyper_Shot&diff=21556Konami Hyper Shot2024-01-19T08:16:05Z<p>Fiskbit: Adds controllers category.</p>
<hr />
<div>The Konami Hyper Shot is used (and required for gameplay) in the following games:<br />
*''Hyper Olympic (J) Konami (1985)''<br />
*''Hyper Sports (J) Konami (1985)''<br />
<br />
== Hardware interface ==<br />
<br />
=== Input ($4016 write) ===<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xEFx<br />
||<br />
|+- 0=Enable Player 1 Buttons<br />
+-- 0=Enable Player 2 Buttons<br />
<br />
<br />
=== Output ($4017 read) ===<br />
<br />
7 bit 0<br />
---- ----<br />
xxxD CBAx<br />
| |||<br />
| ||+-- Player 1 Run<br />
| |+--- Player 1 Jump<br />
| +---- Player 2 Run<br />
+------ Player 2 Jump<br />
<br />
The Jump/Run bits for a player will always be 0 if the corresponding enable bit in $4016 is set.<br />
<br />
== See Also ==<br />
* [//youtu.be/6PSbI03aGKc video of outside, teardown, and game play]<br />
* [//segaretro.org/HyperShot SG-1000 version]<br />
[[Category:Controllers]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Family_Computer_Disk_System&diff=21555Family Computer Disk System2024-01-18T08:57:11Z<p>Fiskbit: Adds an infobox and FDS image.</p>
<hr />
<div>[[File:Nintendo-Famicom-Disk-System.jpg|300px|thumb|right|Famicom, FDS RAM adapter, and FDS disk drive]]<br />
<div class="infobox"><br />
<div style="text-align: center">'''FDS'''</div><br />
{| class="oddf0 floatright"<br />
| '''Company'''<br />
| Nintendo<br />
|-<br />
| '''Complexity'''<br />
| ASIC<br />
|-<br />
| '''Pinout'''<br />
| [[RP2C33 pinout]]<br />
|-<br />
| '''BIOS PRG ROM size'''<br />
| 8K<br />
|-<br />
| '''PRG RAM capacity'''<br />
| 32K<br />
|-<br />
| '''CHR capacity'''<br />
| 8K<br />
|-<br />
| '''Disk capacity'''<br />
| ~64K per side<br />
|-<br />
| '''Mirroring'''<br />
| H or V, switchable<br />
|-<br />
| '''Bus conflicts'''<br />
| No<br />
|-<br />
| '''IRQ'''<br />
| Yes<br />
|-<br />
| '''Audio'''<br />
| Yes<br />
|}</div><br />
The '''Famicom Disk System''' was a Japan-exclusive storage device for the Famicom, designed to reduce Nintendo's cost of making copies of games by switching from mask [[ROM]] chips to a storage medium based on Mitsumi's Quick Disk.<br />
Unfortunately for Nintendo, it also reduced the pirates' cost of making copies of games. Games are stored on one or multiple disk sides. The [[FDS BIOS]] is used to load data from disks to PRG RAM or VRAM, and games can execute from there.<br />
<br />
== Hardware ==<br />
<br />
The Famicom disk system comes in two parts: The disk drive and the RAM adapter.<br />
<br />
The RAM adapter is a special shaped cartridge that contains the RAM chips and an ASIC with DRAM controller, IRQ hardware, sound generation hardware, serial interface for the disk drive, and parallel port. The Disk Drive has to be powered separately and is only connected to the Famicom/NES via a [[FDS RAM adaptor cable pinout|serial cable]] to the RAM adapter.<br />
<br />
Most disk drives contain two motors: a spindle motor that spins the disk at a specific speed, and a stepper motor which moves the read/write head between each circular data track. By comparison, the FDS only contains a single motor that does both at once, so it instead stores the data in a single spiral-shaped track. There is a mechanism that detects when the head reaches the end of the disc and makes it return to the start (making an audible click). Because of this limitation, random access to the disc is impossible, making FDS disk drive data access behave similarly to a reel of tape (but ''much'' faster). Data can only be accessed by spinning the disc, waiting for the head to reach the inner edge of the disc, then waiting again until the desired data file is reached. A complete cycle through the entire disc takes about 7 seconds.<br />
<br />
The disc drive only contains basic electronics, there is no "intelligence" in it; therefore, the serial interface almost directly represents what is stored on the disc.<br />
<br />
=== Disks ===<br />
<br />
The FDS disk is a modified version of the Mitsumi Quick Disk.<br />
<br />
See:<br />
* [[FDS disk format]] - the disk data format and file structure<br />
* [[FDS file format]] (.FDS) - an archival file format for storing and emulating FDS disks<br />
<br />
== Registers ==<br />
<br />
$402x registers are write-only,<br />
$403x registers are read-only<br />
<br />
=== Timer IRQ reload value low ($4020) ===<br />
<br />
7 bit 0<br />
---------<br />
LLLL LLLL<br />
|||| ||||<br />
++++-++++- 8 LSB of timer IRQ reload value<br />
<br />
=== Timer IRQ reload value high ($4021) ===<br />
<br />
7 bit 0<br />
---------<br />
LLLL LLLL<br />
|||| ||||<br />
++++-++++- 8 MSB of timer IRQ reload value<br />
<br />
Unlike $4022, $4020 and $4021 are not affected by the $4023.0 (disk registers enabled) flag - the reload value can be altered even when disk registers are disabled.<br />
<br />
=== Timer IRQ control ($4022) ===<br />
<br />
7 bit 0<br />
---------<br />
xxxx xxER<br />
||<br />
|-- Timer IRQ Repeat Flag<br />
+-- Timer IRQ Enabled<br />
<br />
When $4022 is written to with bit 1 (IRQ enabled) set, the reload value is copied into the IRQ's counter.<br />
Each CPU clock cycle the counter is decremented by one if the enable flag is set.<br />
<br />
When the counter's value is 0 and the IRQ enable flag is on, the following happens on every CPU cycle:<br />
* An IRQ is generated.<br />
* The IRQ counter is reset to its reload value (contained in $4020+$4021)<br />
* If the IRQ repeat flag is NOT set, the IRQ enabled flag is cleared and the counter stops.<br />
<br />
Notes:<br />
* This register is affected by the $4023.0 (Enable disk I/O registers) flag - if disk registers are disabled, it is impossible to start the IRQ counter (writing to $4022 has no effect).<br />
* Clearing $4023.0 will immediately stop the IRQ counter and acknowledge any pending timer IRQs.<br />
* Writing to $4022 with bit 1 (IRQ enabled) cleared will stop the IRQ counter and acknowledge any pending timer IRQs.<br />
* Enabling timer IRQs when the reload value is set to 0 will cause an IRQ immediately. Doing this with the repeat flag enabled will cause an infinite loop of IRQs on every CPU cycle.<br />
* Since the disk transfer routine also uses IRQs, it's very important to disable timer IRQs before doing any access to the disk.<br />
<br />
There are only 3 known ways to acknowledge the timer IRQ:<br />
* Read $4030<br />
* Disable timer IRQs by writing to $4022<br />
* Disable disk registers by writing to $4023<br />
<br />
=== Master I/O enable ($4023) ===<br />
<br />
7 bit 0<br />
---------<br />
xxxx xxSD<br />
||<br />
|+- Enable disk I/O registers<br />
+-- Enable sound I/O registers<br />
<br />
The FDS BIOS writes $00, then $83 to it during reset. The purpose of bit 7 is unknown.<br />
<br />
Disabling disk registers disables both disk and timer IRQs.<br />
<br />
=== Write data register ($4024) ===<br />
<br />
The data that this register is programmed with will be the next 8-bit quantity to load into the shift register (next time the byte transfer flag raises), and to be shifted out and appear on pin 5 of the RAM adapter cable (2C33 pin 52).<br />
<br />
Writing to this register acknowledges disk IRQs.{{Citation needed}}<br />
<br />
=== FDS Control ($4025) ===<br />
7 bit 0<br />
---------<br />
IS1B MRTD<br />
|||| ||||<br />
|||| |||+- Drive Motor Control (0: stop, 1: start)<br />
|||| ||+-- Transfer Reset (TODO)<br />
|||| || 1: Reset transfer timing to the initial state.<br />
|||| |+--- Transfer Mode (0: write; 1: read)<br />
|||| +---- Mirroring (0: vertical; 1: horizontal)<br />
|||+------ CRC Control (1: transfer CRC values)<br />
||+------- Always set to '1'<br />
|+-------- Transfer Behaviour<br />
| (TODO)<br />
+--------- Interrupt Enabled<br />
1: Generate an IRQ every time the byte transfer flag is raised.<br />
<br />
Notes:<br />
* The BIOS sets the CRC Control to 1 while handling CRC values. ''TODO: document CRC handling''<br />
* <br />
<br />
An FDS game that wants to change mirroring probably doesn't want to touch motor related bits, so it should do a read-modify-write from the pseudo registers (see [[FDS BIOS]]).<br />
<br />
Writing to this register acknowledges disk IRQ.<br />
<br />
=== External connector ($4026) ===<br />
<br />
Output of expansion terminal where there's a shutter on the back of the ram card. The outputs of $4026 (open-collector with 4.7K ohm pull-ups (except on bit 7)), are shared with the inputs on $4033.<br />
<br />
=== Disk Status register ($4030) ===<br />
7 bit 0<br />
---------<br />
IExB xxTD<br />
|| | ||<br />
|| | |+- Timer Interrupt (1: an IRQ occurred)<br />
|| | +-- Byte transfer flag. Set every time 8 bits have been transferred between the RAM adaptor & disk drive (service $4024/$4031). <br />
|| | Reset when $4024, $4031, or $4030 has been serviced.<br />
|| +------ CRC control (0: CRC passed; 1: CRC error)<br />
|+-------- End of Head (1 when disk head is on the most inner track)<br />
+--------- Disk Data Read/Write Enable (1 when disk is readable/writeable)<br />
<br />
Reading this register acknowledges timer and disk IRQs.<br />
<br />
=== Read data register ($4031) ===<br />
<br />
This register is loaded with the contents of an internal shift register every time the byte transfer flag raises. The shift register receives its serial data via pin 9 of the RAM adapter cable (2C33 pin 51).<br />
<br />
Reading this register acknowledges disk IRQs.<br />
<br />
=== Disk drive status register ($4032) ===<br />
7 bit 0<br />
---------<br />
xxxx xPRS<br />
|||<br />
||+- Disk flag (0: Disk inserted; 1: Disk not inserted)<br />
|+-- Ready flag (0: Disk readу; 1: Disk not ready)<br />
+--- Protect flag (0: Not write protected; 1: Write protected or disk ejected)<br />
<br />
Reading this register acknowledges disk IRQs.{{Citation needed}}<br />
<br />
=== External connector read ($4033) ===<br />
7 bit 0<br />
---------<br />
BIII IIII<br />
|||| ||||<br />
|+++-++++- Input from expansion terminal where there's a shutter on the back of the ram card.<br />
+--------- Battery status (0: Voltage is low; 1: Good).<br />
<br />
When a bit is clear in $4026 port it will read back as '0' here (including battery bit) because of how open collector input works. Battery bit should be checked when the motor is on, otherwise it always will be read as 0.<br />
<br />
=== Sound ($4040-$4092) ===<br />
<br />
For details on sound information, see [[FDS_audio|FDS audio]].<br />
<br />
== BIOS ==<br />
<br />
The FDS contains a fixed 8KB BIOS at $E000-FFFF. This controls the Famicom at power-on and reset, dispatches the NMI and IRQ, and offers an API for accessing the [[FDS disk format|data on disk]].<br />
<br />
See: [[FDS BIOS]]<br />
<br />
== See Also ==<br />
<br />
* [[FDS BIOS]]<br />
* [[FDS disk format]]<br />
* [[FDS file format]] ('''.FDS''')<br />
* [[FDS audio]]<br />
* [[FDS RAM adaptor cable pinout]]<br />
* [[RP2C33 pinout]]<br />
* [[iNES mapper 020|iNES mapper 20]] - Reserved for FDS dumps, but not widely used for it.<br />
* [https://github.com/bbbradsmith/NES-ca65-example/tree/fds Github repository:] Simple FDS example for ca65<br />
* [//forums.nesdev.org/viewtopic.php?p=194826#p194826 Forum post:] Skipping the FDS license screen<br />
<br />
== References ==<br />
<br />
* [//nesdev.org/FDS%20technical%20reference.txt FDS technical reference.txt] by Brad Taylor<br />
* [http://cmpslv2.starfree.jp/Famic/Famdis.htm Enri's Famicom Disk System page] (Japanese)<br />
* [https://web.archive.org/web/20091023182159/http://www2.odn.ne.jp/~haf09260/Famic/Famdis.htm Enri's Famicom Disk System page] (Japanese) (old/outdated)<br />
* [//nesdev.org/fds-nori.txt fds-nori.txt] - FDS reference in Japanese by Nori<br />
* [https://www.chrismcovell.com/software.html FDS List] by ccovell - command line utility to inspect FDS disk image contents.<br />
* [https://www.chrismcovell.com/fds-lister.html FDS Lister] by ccovell - utility to inspect FDS disk contents that runs on an FDS.<br />
* [//forums.nesdev.org/viewtopic.php?p=194867#p194867 Forum post]: .fds format: Can checksums be heuristically detected? - Includes a CRC implementation in C.<br />
* [//forums.nesdev.org/viewtopic.php?f=3&t=16507 Forum post]: FDS IRQ reload flag/value<br />
<references/><br />
<br />
[[Category:Mappers using $4020-$5FFF]][[Category:Mappers with cycle IRQs]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Nintendo-Famicom-Disk-System.jpg&diff=21554File:Nintendo-Famicom-Disk-System.jpg2024-01-18T06:29:14Z<p>Fiskbit: A Famicom plus Famicom Disk System. The disk drive connects through a cable on the RAM adapter cartridge.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
A Famicom plus Famicom Disk System. The disk drive connects through a cable on the RAM adapter cartridge.<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Super_NES_Mouse&diff=21553Super NES Mouse2024-01-18T05:27:28Z<p>Fiskbit: Adds an SNES mouse image.</p>
<hr />
<div>[[File:SNES-Mouse-and-Pad.jpg|400px|thumb|right|SNES mouse]]<br />
The '''Super NES Mouse''' (SNS-016) is a peripheral for the Super NES that was originally bundled with ''Mario Paint''.<br />
It can be used with an NES through an adapter, made from an NES controller extension cord and a Super NES controller extension cord, that [[Controller port pinout|connects the respective power, ground, clock, latch, and data pins]].<br />
The '''Hyper Click Retro Style Mouse''' by Hyperkin is an optical mouse mostly compatible with software for the Super NES Mouse, with some behavior quirks.<br />
<br />
As with the [[standard controller]], the mouse is read by turning the latch ($4016.d0) on and off, and then reading bit 0 or bit 1 of $4016 or $4017 several times, but its report is 32 bits long as opposed to 8 bits.<br />
<br />
On an NES or AV Famicom, the mouse may be connected to bit 0 through the front controller ports. On the original Famicom, it would normally have to be connected to bit 1 instead through the expansion port.<br />
<br />
== Report ==<br />
<br />
The report is divided functionally into four bytes. The most significant bit is delivered first:<br />
<pre><br />
76543210 First byte<br />
++++++++- Always zero: 00000000<br />
<br />
76543210 Second byte<br />
||||++++- Signature: 0001<br />
||++----- Current sensitivity (0: low; 1: medium; 2: high)<br />
|+------- Left button (1: pressed)<br />
+-------- Right button (1: pressed)<br />
<br />
76543210 Third byte<br />
|+++++++- Vertical displacement since last read<br />
+-------- Direction (1: up; 0: down)<br />
<br />
76543210 Fourth byte<br />
|+++++++- Horizontal displacement since last read<br />
+-------- Direction (1: left; 0: right)<br />
</pre><br />
<br />
After the fourth byte, subsequent bits will read as all 1, though the Hyperkin clone mouse instead reads a single 1 then all 0s. <ref>[//forums.nesdev.org/viewtopic.php?p=231607#p231607 forum post]: Hyperkin SNES mouse investigation</ref><br />
<br />
The Hyper Click mouse will not give a stable report if it is read too fast. Between each read and the next, there should be at least 14 CPU cycles. Between the 2nd and 3rd byte (16th and 17th bit) of the report should be at least 28 CPU cycles. Reading faster than this will result in corrupted values.<ref>[//forums.nesdev.org/viewtopic.php?p=236484#p236484 forum post]: Hyperkin mouse reads have a speed limit</ref>.<br />
<br />
== Motion ==<br />
<br />
Motion of the mouse is given as a displacement since the last mouse read, delivered in the third and fourth bytes of the report.<br />
<br />
The displacements are in [[wikipedia:Signed number representations#Sign-and-magnitude method|sign-and-magnitude]], not [[wikipedia:Signed number representations#Two's complement|two's complement]].<br />
For example, $05 represents five mickeys (movement units) in one direction and $85 represents five mickeys in the other.<br />
To convert these to two's complement, use [[Synthetic instructions#Negate A|negation]]:<br />
<pre><br />
; Convert to two's complement<br />
lda third_byte<br />
bpl :+<br />
eor #$7F<br />
sec<br />
adc #$00<br />
:<br />
sta y_velocity<br />
<br />
lda fourth_byte<br />
bpl :+<br />
eor #$7F<br />
sec<br />
adc #$00<br />
:<br />
sta x_velocity<br />
</pre><br />
<br />
When the magnitude of motion is 0, the reported sign will repeat the last used sign value for that coordinate.<br />
<br />
== Sensitivity ==<br />
<br />
The mouse can be set to low, medium, or high sensitivity.<br />
<br />
On the original SNES mouse this can be changed by sending a clock while the latch ($4016.d0) is turned on:<br />
<pre><br />
ldy #1<br />
sty $4016<br />
lda $4016<br />
dey<br />
sty $4016<br />
</pre><br />
<br />
Some revisions of the mouse's microcontroller power up in an unknown state and may return useless values before the sensitivity is changed for the first time.<ref name="fullsnes">Martin Korth. "[//problemkaputt.de/fullsnes.htm#snescontrollersmousetwobuttonmouse Fullsnes: SNES Controllers Mouse Two Button Mouse]".</ref><br />
<br />
The Hyper Click mouse will not cycle its sensitivity this way. Instead it has a manual button on the underside that must be pressed by the user to cycle sensitivity. It will always report 0 for sensitivity, regardless of its manual setting. For this reason, it is not advised to use the software sensitivity cycling to automatically detect the presence of a mouse.<ref>[//forums.nesdev.org/viewtopic.php?p=231600#p231600 forum post]: Hyperkin SNES Mouse cannot software-cycle sensitivity</ref><br />
<br />
On the original SNES mouse, sensitivity setting 0 responds linearly to motion, at a rate of 50 counts per inch<ref>[http://problemkaputt.de/fullsnes.htm#snescontrollersmousetwobuttonmouse FullSNES] - Nocash SNES Mouse documentation</ref>. Values range from 0 to 63, but values higher than 25 are increasingly difficult to produce. <ref>[//forums.nesdev.org/viewtopic.php?p=232667#p232667 forum post]: SNES Mouse sensitivity measurements</ref><br />
<br />
Sensitivity settings 1 and 2 appear to remap the equivalent setting 0 values 0-7 to a table, and clamping at the highest value. (Rarely, however, other values may be seen in settings 1 and 2.)<br />
{| class="wikitable"<br />
|-<br />
! Sensitivity<br />
! colspan = "11" | Value<br />
|-<br />
! 0<br />
| 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || ...<br />
|-<br />
! 1<br />
| 0 || 1 || 2 || 3 || 8 || 10 || 12 || 21 || 21 || 21 || ...<br />
|-<br />
! 2<br />
| 0 || 1 || 4 || 9 || 12 || 20 || 24 || 28 || 28 || 28 || ...<br />
|}<br />
<br />
The Hyper Click's two manually selected sensitivities both scale linearly with motion speed. Low sensitivity produces 0-31, and high sensitivity produces 0-63. The magnitude of the result is not dependent on the rate of polling, so it appears to report the current speed rather than the distance travelled since the last poll. The maximum value (31/63) at either sensitivity appears to correspond roughly to a speed of 8 inches per second. (This mouse should be used on a surface with a visible texture.)<ref>[//forums.nesdev.org/viewtopic.php?p=232668#p232668 forum post]: Hyperkin Mouse sensitivity measurements</ref><br />
<br />
== Other notes ==<br />
<br />
A program that reads the mouse while playing [[APU DMC|DPCM samples]] must proceed very carefully.<br />
Sample playback causes occasional double reads on $4016 and $4017, deleting a bit from the stream read back.<br />
The re-reading solution that can be used for the [[standard controller]] fails here because each latch pulse sent to a mouse will clear its count of accumulated movement, and there is no known way to reliably detect corrupted data.<br />
Only the [[Controller reading#Synchronized OAM Solution|OAM DMA sync trick]] reliably avoids these glitches.<br />
<br />
Using more than two mice on an AV Famicom is not recommended for two reasons:<br />
* A mouse draws 50 mA, which is much more current than the standard controller draws. Drawing too much current is likely to cause the voltage regulator to overheat.<br />
* Changing player 1's sensitivity also affects player 3's, and changing player 2's sensitivity also affects player 4's.<br />
<br />
Some documents about interfacing with the mouse recommend reading the first 16 bits at one speed, delaying a while, and reading the other 16 bits at another speed, following logic analyzer traces from a Super NES console.<br />
However, these different speeds are merely an artifact of the main loop of ''Mario Paint'', and the authentic mouse will give a correct report when read at any reasonable speed.<br />
For example, a program could read 8 bits, wait a couple thousand cycles, and then read the other 24.<br />
The Hyper Click needs a delay after the first 16 bits, though not nearly as much as these documents recommend.<br />
<br />
== Example games ==<br />
Games<br />
* ''[[User:Tepples/Thwaite|Thwaite]]''<br />
* ''[[Action 53|Sliding Blaster]]''<br />
* ''[https://rainwarrior.itch.io/nesert-golfing NESert Golfing]''<br />
Applications<br />
* ''[[Action 53|Theremin]]''<br />
* [[Audio_drivers#Pently|Pently Sound Effects Editor]]<br />
* The menu of any ''[[Action 53]]'' volume including a game or application with mouse support<br />
Tests<br />
* [https://github.com/pinobatch/little-things-nes/tree/master/meece Meece], the first<br />
* [[Emulator Tests#Input Tests|allpads]]<br />
* [https://github.com/pinobatch/240p-test-mini 240p Test Suite]<br />
<br />
== References ==<br />
:*[//snes.nesdev.org/wiki/Mouse Mouse] at SNESdev Wiki<br />
<references /><br />
[[Category:Controllers]]<br />
[[Category:Pointing devices]]<br />
[[Category:Super NES]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:SNES-Mouse-and-Pad.jpg&diff=21552File:SNES-Mouse-and-Pad.jpg2024-01-18T05:26:40Z<p>Fiskbit: The SNES mouse.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The SNES mouse.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=SNES_controller&diff=21551SNES controller2024-01-18T05:26:01Z<p>Fiskbit: Adds an SNES controller image.</p>
<hr />
<div>[[File:SNES-Controller-Flat.jpg|400px|thumb|right|Standard SNES controller]]<br />
The '''Super NES Controller''' (SHVC-005, SNS-005, SNS-102) is very similar to the NES's [[standard controller]], with a collection of digital inputs that are latched and read in series. With a [[Controller port pinout|suitable adapter]], reading the SNES controller is like reading an NES controller with 4 extra buttons.<br />
<br />
[[Category:Controllers]]<br />
[[Category:Super NES]]<br />
<br />
The 16 bit report will read, in order:<br />
<br />
0 - B<br />
1 - Y<br />
2 - Select<br />
3 - Start<br />
4 - Up<br />
5 - Down<br />
6 - Left<br />
7 - Right<br />
<br />
8 - A<br />
9 - X<br />
10 - L<br />
11 - R<br />
12 - 0<br />
13 - 0<br />
14 - 0<br />
15 - 0<br />
<br />
Note that the first 8 values map directly to the original NES controller's 8 inputs (SNES '''B''' = NES '''A''', and SNES '''Y''' = NES '''B'''). The [[Virtual Boy controller]] likewise returns button states in nearly the same order, with the right Control Pad corresponding to ABXY on the Super NES.<br />
<br />
The last 4 bits will always read 0 from a standard SNES controller. Other values here may indicate other devices,<ref>[http://problemkaputt.de/fullsnes.htm#snescontrollershardwareidcodes FullSNES:] SNES Controller Hardware ID Codes</ref> such as a [[mouse]] or a Virtual Boy controller.<br />
<br />
After the 16 bit report, subsequent bits will read as 1.<br />
<br />
== Games ==<br />
An incomplete list of NES games with special support for SNES controllers:<br />
<br />
* ''Spook-O-Tron''<br />
* ''Nova the Squirrel''<ref>[https://forums.nesdev.org/viewtopic.php?p=198552#p198552 Nova the Squirrel (WIP)] - forum post discussing SNES controller support.</ref><br />
* ''Full Quiet''<ref>[https://twitter.com/ecmyers/status/1600574149092589569 Tweet by E.C. Myers]</ref><br />
<br />
== See also ==<br />
* [[Controller port pinout]]<br />
* [[Controller reading]]<br />
<br />
== References ==<br />
:*[//snes.nesdev.org/wiki/Standard_controller Standard controller] at SNESdev Wiki<br />
<References/></div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:SNES-Controller-Flat.jpg&diff=21550File:SNES-Controller-Flat.jpg2024-01-18T05:24:41Z<p>Fiskbit: The standard SNES controller.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The standard SNES controller.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=R.O.B.&diff=21549R.O.B.2024-01-18T05:23:12Z<p>Fiskbit: Adds a ROB image.</p>
<hr />
<div>[[File:NES-ROB.jpg|200px|thumb|right|NES R.O.B.]]<br />
<blockquote>R.O.B. (Robotic Operating Buddy) is a toy robot accessory for the Nintendo Entertainment System (NES). It was launched in July 1985 as the Family Computer Robot in Japan, and October 1985 as R.O.B. in North America. Its short lifespan yielded only two games in the Robot Series: Gyromite and Stack-Up.<br />
</blockquote><blockquote>The R.O.B. unit's height is 24 cm (9.6 in). It has a head movement range of a 45° horizontally centered tilt. The arm movement range is 240° left and right with five stopping points, 7 cm (2.75 in) up and down with six stopping points, and 7 cm (2.75 in) between hands when open. The unit has five accessory slots around the hexagonal base, numbered clockwise, starting at the rear-left from the robot's point of view; and notches on the hands allow for specialized parts to be attached for each game. The tinted filter can be optionally attached over the eyes like sunglasses, to compensate for bright televisions or sunlight. The unit is powered by four AA batteries.</blockquote> - from [[wikipedia:R.O.B.|wikipedia]]<br />
<br />
The protocol consists of a series of flashes of light, one bit per vertical sync. It takes 13 vertical syncs (or possibly 14—if Z is 1, the following field must be 0. [https://atariage.com/forums/topic/177286-any-interest-in-nes-rob-homebrews/?tab=comments#comment-2217299]) to send a command:<br />
<br />
000101w1x1y1z<br />
<br />
Ten commands are known to exist:<br />
{| class="sortable"<br />
! wxyz !! command<br />
|-<br />
| 0101 || Up 2 steps<br />
|-<br />
| 1100 || Up 1 step<br />
|-<br />
| 0010 || Down 1 step<br />
|-<br />
| 1101 || Down 2 steps<br />
|-<br />
| 0100 || Turns the body left<br />
|-<br />
| 1000 || Turns the body right<br />
|-<br />
| 0110 || Close the arms<br />
|-<br />
| 1010 || Open the arms<br />
|-<br />
| 1001 || Turn the head LED on permanently<br />
|-<br />
| 0001 || Reset = turn LED off, open arms, seek rightmost/upmost, then go back to center.<br />
|}<br />
The other six possible messages have no result.<br />
<br />
Additionally, an endless stream of 25 or 30 Hz flashes will cause the LED to blink when R.O.B. sees light from the TV. This helps with aiming the head.<br />
<br />
A dump of the firmware has been made [http://www.seanriddle.com/sm590/ here], and it has now been disassembled: [[R.O.B. Firmware]]<br />
<br />
It is not known how wide R.O.B.'s field of view is, but the light sensor is that same as the [[Zapper]]'s.<br />
<br />
See also: <br />
* [https://learn.adafruit.com/controlling-a-classic-nintendo-r-o-b-robot-using-circuit-playground-express?view=all Controlling R.O.B. with a microcontroller]<br />
* [http://problemkaputt.de/everynes.htm#robroboticoperatingbuddy Nocash's EveryNES § R.O.B.]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:NES-ROB.jpg&diff=21548File:NES-ROB.jpg2024-01-18T05:20:50Z<p>Fiskbit: The NES R.O.B. (Robotic Operating Buddy), a device separate from the console that is controlled by flashing on the TV and capable of pressing controller buttons.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The NES R.O.B. (Robotic Operating Buddy), a device separate from the console that is controlled by flashing on the TV and capable of pressing controller buttons.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Four_player_adapters&diff=21547Four player adapters2024-01-18T04:48:27Z<p>Fiskbit: Adds a Four Score image.</p>
<hr />
<div>Four player adapters are devices that plug into controller or expansion ports and provide additional ports. These ports can be used as alternatives to hardwired controllers or for multiplayer with more than 2 simultaneous players. Contemporary adapters allow some consoles to interface with up to 8 controllers. These adapters come in multiple forms, each with their own interfaces and limitations.<br />
<br />
=Adapters=<br />
<br />
=="Simple" Famicom adapters==<br />
Because the Famicom only has one expansion port, a device such as the '''JoyPair''' or '''Twin Adapter''' is required to attach multiple controllers to it. Standard expansion controllers respond on D1 of $4016, and these multi-port devices redirect the second port to D1 of $4017. These may be used as players 3 and 4. In 1- or 2-player games for the Famicom, though, it is common to OR together the D1 and D0 bits of a joypad read to allow players to use external controllers as substitutes for the hardwired ones.<br />
<br />
The expansion ports on these multi-port devices do not pass through all of the signals and thus are limited in functionality compared to the console's expansion port. Because of this, many controllers are not compatible with these adapters.<br />
<br />
=== Pinout ===<br />
JoyPair CN1 | | Famicom EXP<br />
-----------------+--+-----------------<br />
GND 01 |--| 01 GND<br />
OUT0 12 |<-| 12 OUT0<br />
Joypad 1 /D1 13 |->| 13 Joypad 1 /D1<br />
Joypad 1 /OE 14 |<-| 14 Joypad 1 /OE<br />
5V 15 |--| 15 5V<br />
<br />
JoyPair CN2 | | Famicom EXP<br />
-----------------+--+-----------------<br />
GND 01 |--| 01 GND<br />
OUT0 12 |<-| 12 OUT0<br />
Joypad 1 /D1 13 |->| 07 Joypad 2 /D1<br />
Joypad 1 /OE 14 |<-| 09 Joypad 2 /OE<br />
5V 15 |--| 15 5V<br />
<br />
(All other JoyPair pins not connected)<br />
<br />
==Hori 4 Players Adapter==<br />
<br />
The '''Hori 4 Players Adapter''' is a Famicom expansion port device that provides 4 ports, usable in 2- and 4-controller modes selected using a switch. In 2-controller mode, ports 1 and 2 on the adapter function exactly like a "simple" Famicom adapter, and ports 3 and 4 are disabled. In 4-controller mode, ports 1 and 3 are multiplexed onto $4016 D1 and ports 2 and 4 onto $4017 D1. The first 8 reads from an address provide the joypad 1 D1 report from the first controller, the next 8 reads the joypad 1 D1 report from the second controller, and the next 8 reads a signature unique to that address. The read counter is reset as long as OUT0 is 1. The same connection limitations of the "simple" adapters still apply in 4-controller mode, which combined with the 8 read limit restricts the set of usable contemporary controllers to those compatible with the standard controller.<br />
<br />
===Protocol===<br />
==== Input ($4016 write) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxS<br />
|<br />
+- Controller read strobe<br />
<br />
This matches the normal strobe behavior used by the [[Standard_controller#Input_.28.244016_write.29|standard controller]] and strobes all 4 at once.<br />
<br />
==== Output ($4016/$4017 read) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxDx<br />
|<br />
+-- Serial controller data<br />
<br />
==== Report ====<br />
<br />
$4016 read D1:<br />
0-7 - Joypad 1 D1 bits 0-7 from controller #1<br />
8-15 - Joypad 1 D1 bits 0-7 from controller #3<br />
16-17 - (Always 0)<br />
18 - (Always 1)<br />
19-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
$4017 read D1:<br />
0-7 - Joypad 1 D1 bits 0-7 from controller #2<br />
8-15 - Joypad 1 D1 bits 0-7 from controller #4<br />
16-18 - (Always 0)<br />
19 - (Always 1)<br />
20-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
Note: ''Joypad 1'' and ''joypad 2'' are names used on the controller-side [[Expansion_port#Famicom|Famicom expansion port]] pin interface, as compared to $4016 and $4017 on the CPU side. While joypad 1 normally connects to $4016, this adapter routes each controller's joypad 1 /D1 to $4016 or $4017 as needed.<br />
<br />
==Four Score==<br />
<br />
[[File:NES-Four-Score.jpg|200px|thumb|right|NES Four Score]]<br />
The Four Score is an adapter that plugs into both NES controller ports and provides 4 ports, usable in 2- and 4-controller modes. This device is nearly identical to the Hori 4 Players Adapter, differing in that D0 is used instead of D1 and the addresses' signatures are swapped. This device also provides two turbo switches.<br />
<br />
===Protocol===<br />
==== Input ($4016 write) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxS<br />
|<br />
+- Controller read strobe<br />
<br />
This matches the normal strobe behavior used by the [[Standard_controller#Input_.28.244016_write.29|standard controller]] and strobes all 4 at once.<br />
<br />
==== Output ($4016/$4017 read) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxD<br />
|<br />
+- Serial controller data<br />
<br />
==== Report ====<br />
<br />
$4016 read D0:<br />
0-7 - Joypad D0 bits 0-7 from controller #1<br />
8-15 - Joypad D0 bits 0-7 from controller #3<br />
16-18 - (Always 0)<br />
19 - (Always 1)<br />
20-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
$4017 read D0:<br />
0-7 - Joypad D0 bits 0-7 from controller #2<br />
8-15 - Joypad D0 bits 0-7 from controller #4<br />
16-17 - (Always 0)<br />
18 - (Always 1)<br />
19-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
Note: ''Joypad D0'' refers to the data normally available on $4016 or $4017 bit 0. Unlike the Famicom expansion port, NES controller port wiring is relative to the port used, so while a controller normally chooses which data inputs to use, it does not choose whether those are joypad 1 or joypad 2.<br />
<br />
===Turbo===<br />
<br />
The Four Score includes separate turbo enables intended for the A and B buttons. Each of these applies universally to all attached controllers and in both 2- and 4-controller modes. These turbos force their respective bits to 0 at a fixed rate by ANDing with a mask that alternates between 0 and 1, making a held button appear as though it is being rapidly pressed and released. After a strobe, the A turbo applies to the first read of each controller's report and the B turbo to the second read. In 2-controller mode, each turbo also applies again after every 32 additional reads, causing toggles in the stream of 1's that follow the report from official controllers.<br />
<br />
The toggle rate is based on the Four Score's internal clock and is approximately 2 frames.<br />
<br />
==NES Satellite==<br />
<br />
[[File:NES-Satellite.jpg|200px|thumb|right|top|NES Satellite]]<br />
The NES Satellite is a 4-controller wireless adapter similar to the Four Score. Specific details are not yet known. Instead of a mode switch for 2 or 4 controllers, the NES Satellite has a mode switch selecting between standard controllers and the Zapper. Like the Four Score, it also features A and B turbo switches.<br />
<div style="clear: both"></div><br />
<br />
=Hardware=<br />
<br />
Inside the Four Score and 4 Players Adapter is a 22-pin DIP labeled [[FPA-PAL-S01 pinout|FPA-S01]]. This IC consists of a decoder and one set of shift register, 5-bit counter, and multiplexer per joypad address, allowing each address to return the 8-bit contents of joypads 1 and 3 or 2 and 4 in series, followed by the signature byte.<br />
<br />
In case you want to build a four player adapter into an arcade cabinet or some other permanent installation, you don't need to use a Four Score or other adapter: you just need six total shift registers. The inputs to these shift registers are parallel, so you need separate wires for each signal, like from SMS or ZX Spectrum controllers.<br />
<br />
=5+ controllers=<br />
<br />
These adapters can be used in combination with each other on the AV Famicom for up to 8 controllers, or on the Famicom with the hardwired controllers for up to 6. Because nonstandard controllers are not compatible with 4-controller modes, using them reduces the maximum possible controller count, but if a single nonstandard controller such as a mouse is desired, it can be used with a "simple" adapter alongside up to 6 standard controllers on an AV Famicom using a Four Score in the NES controller ports, a "simple" adapter in the expansion port, and a Hori 4 Players Adapter with controllers in ports 1 and 3 in the other "simple" adapter port.<br />
<br />
=Compatible Games=<br />
<br />
Games known to support 3 or more simultaneous controllers:<br />
{| class="sortable wikitable"<br />
! Game !! Hori 4-player Adapter !! Four Score !! Simple<br />
|-<br />
| A Nightmare on Elm Street || yes || yes || ?<br />
|-<br />
| Bomber Man II (J) || no || no || yes<br />
|-<br />
| Bomberman II (U) || no || yes || ?<br />
|-<br />
| Downtown Nekketsu Koushinkyoku: Soreyuke Daiundoukai || yes || yes || yes<br />
|-<br />
| Gauntlet II || no || yes || no<br />
|-<br />
| Greg Norman's Golf Power || yes || yes || ?<br />
|-<br />
| Harlem Globetrotters || no || yes || ?<br />
|-<br />
| Ike Ike! Nekketsu Hockey Bu: Subette Koronde Dai Rantou || no || ? || yes<br />
|-<br />
| Indy Heat || yes || yes || ?<br />
|-<br />
| Kings of the Beach || yes || yes || ?<br />
|-<br />
| Kunio-kun no Nekketsu Soccer League || no || unlikely || yes<br />
|-<br />
| M.U.L.E. || no || yes || ?<br />
|-<br />
| Magic Johnson's Fast Break || yes || yes || ?<br />
|-<br />
| Millionaire (Sachen) || no || no || yes<br />
|-<br />
| Moero TwinBee: Cinnamon-hakase o Sukue! || no || ? || yes<br />
|-<br />
| Monster Truck Rally || no || yes || ?<br />
|-<br />
| NES Play Action Football || yes || yes || ?<br />
|-<br />
| Nekketsu Kakutou Densetsu || no || ? || yes<br />
|-<br />
| Nekketsu Koukou Dodge Ball Bu || no || ? || yes<br />
|-<br />
| Nekketsu Street Basket: Ganbare Dunk Heroes || no || ? || yes<br />
|-<br />
| Nintendo World Cup (U) || yes || yes || ?<br />
|-<br />
| R.C. Pro-Am II || yes || yes || ?<br />
|-<br />
| Rackets and Rivals || no || yes || ?<br />
|-<br />
| Roundball: 2-on-2 Challenge || no || yes || ?<br />
|-<br />
| Smash T.V. (twin-stick for 2 players) || no || yes || ?<br />
|-<br />
| Spot || yes || yes || no<br />
|-<br />
| Super Jeopardy! || yes || yes || ?<br />
|-<br />
| Super Off Road || yes || yes || no<br />
|-<br />
| Super Spike V'Ball || everywhere but title screen || everywhere but title screen || yes<br />
|-<br />
| Swords and Serpents || no || yes || ?<br />
|-<br />
| Top Players' Tennis || yes || yes || ?<br />
|-<br />
| U.S. Championship V'Ball || only during 3+player gameplay || only during 3+player gameplay || yes<br />
|-<br />
| Wit's || yes || yes || yes<br />
|}<br />
<br />
Homebrew games:<br />
*''Double Action Blaster Guys'' becomes ''Quadruple Action Blaster Guys'' when Four Score is connected (NES)<br />
*''Micro Mages'' (NES and Famicom)<br />
*''NESert Golfing'' (NES and Famicom)<br />
*''Spacey McRacey'' (NES)<br />
*''Super PakPak'' (NES and Famicom)<br />
<br />
Tech demos:<br />
*''Eighty'' (NES and Famicom)<br />
*''allpads'' (NES and Famicom)<br />
<br />
Hacks:<br />
*''Battle City - 4 Players v1.3 Ti'' (NES and Famicom)<br />
*''Battle City Mario - 4 players v1.0 NesDraug'' (NES and Famicom)<br />
*''Battletoads - 4 players v2.2 NakeuD2007'' (emulator only)<br />
*''Battletoads & Double Dragon - 4 players v0.9 NakeuD2007'' (emulator only)<br />
*''Super Dodge Ball - 4 Player Hack v1.00 akatranslations'' (Famicom)<br />
<br />
=Incompatible Games=<br />
This section lists games that provide four player game modes without supporting a four player adapter. They are explicitly enumerated here because various lists, including one in Wikipedia, frivolously keep listing (and re-adding after an edit to remove them) these games as supporting a four player adapter.<br />
*''Championship Bowling'': Manual clearly states "Players One and Three use Control Pad 1, and Players Two and Four use Control Pad 2".<br />
*''Jeopardy!'' series: Players 1 and 3 share controller 1.<br />
<br />
= References =<br />
<References/><br />
* [//forums.nesdev.org/viewtopic.php?p=237997#p237997 Forum post]: Analysis of Wit's controller reading, and speculation about the Hori 4 Players adapter.<br />
* [http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=65237 NintendoAge forum thread]: Photos of Four Score PCB and hardware discussion.<br />
* [https://www.famicomworld.com/forum/index.php?topic=12543.15 Famicom World forum post]: List of Famicom games and their behaviour with Hori 4 Players adapter.<br />
* [//forums.nesdev.org/viewtopic.php?p=238168#p238168 Forum post]: Discussion of Hori 4 Players support in ''Micro Mages''.<br />
[[Category:Controllers]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:NES-Four-Score.jpg&diff=21546File:NES-Four-Score.jpg2024-01-18T04:47:11Z<p>Fiskbit: The NES Four Score, a four player adapter.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The NES Four Score, a four player adapter.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Standard_controller&diff=21545Standard controller2024-01-18T04:33:56Z<p>Fiskbit: Adds NES and Famicom player 2 controller images.</p>
<hr />
<div>[[File:NES-Controller-Flat.jpg|400px|thumb|right|Standard NES controller]]<br />
All NES units come with at least one standard controller - without it, you wouldn't be able to play any games!<br />
<br />
Standard controllers can be used in both controller ports, or in a [[Four score]] accessory.<br />
<br />
:''For code examples, see: [[Controller reading code]]''<br />
<br />
== Report ==<br />
The standard NES controller will report 8 bits on its data line:<br />
<br />
0 - A<br />
1 - B<br />
2 - Select<br />
3 - Start<br />
4 - Up<br />
5 - Down<br />
6 - Left<br />
7 - Right<br />
<br />
After 8 bits are read, all subsequent bits will report 1 on a standard NES controller, but third party and other controllers may report other values here.<br />
<br />
If using DPCM audio samples, read conflicts must be corrected with a software technique. The most common symptom of this is spurious Right presses as the DPCM<br />
conflict deletes one bit of the report, and an extra 1 bit appears in the Right press position. See: [[Controller reading#DPCM conflict|Controller reading: DPCM conflict]].<br />
<br />
== Input ($4016 write) ==<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxS<br />
|<br />
+- Controller shift register strobe<br />
<br />
While S ([[Glossary|strobe]]) is high, the shift registers in the controllers are continuously reloaded from the button states, and reading $4016/$4017 will keep returning the current state of the first button (A). Once S goes low, this reloading will stop. Hence a 1/0 write sequence is required to get the button states, after which the buttons can be read back one at a time.<br />
<br />
(Note that bits 2-0 of $4016/write are stored in internal latches in the 2A03/07.)<br />
<br />
== Output ($4016/$4017 read) ==<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xMES<br />
|||<br />
||+- Primary controller status bit<br />
|+-- Expansion controller status bit (Famicom)<br />
+--- Microphone status bit (Famicom, $4016 only)<br />
<br />
Though both are polled from a write to $4016, controller 1 is read through $4016, and controller 2 is separately read through $4017.<br />
<br />
Each read reports one bit at a time through D0. The first 8 reads will indicate which buttons or directions are pressed (1 if pressed, 0 if not pressed).<br />
All subsequent reads will return 1 on official Nintendo brand controllers but may return 0 on third party controllers such as the [[U-Force]].<br />
<br />
Status for each controller is returned as an 8-bit report in the following order: A, B, Select, Start, Up, Down, Left, Right.<br />
<br />
In the NES and Famicom, the top three (or five) bits are not driven, and so retain the bits of the previous byte on the bus. Usually this is the most significant byte of the address of the controller port—0x40. Certain games (such as Paperboy) rely on this behavior and require that reads from the controller ports return exactly $40 or $41 as appropriate. ''See: [[Controller reading#Unconnected data lines and open bus|Controller reading: unconnected data lines]].''<br />
<br />
When no controller is connected, the corresponding status bit will report 0. This is due to the presence of internal pull-up resistors, and the internal inverter. (See: [[Controller reading]])<br />
<br />
=== Famicom ===<br />
<br />
[[File:Nintendo-Famicom-Controller-II-FL.jpg|200px|thumb|right|Famicom second-player controller]]<br />
The original Famicom's hard-wired second controller (II) is missing the Select and Start buttons. Its corresponding bits will read as 0, so Famicom games do not rely on the second player being able to push Start or Select.<br />
<br />
This hard-wired second controller also contains a microphone, which gives an immediate 1-bit report at $4016 D2 whenever it is read.<br />
<br />
The later AV Famicom used detachable controllers, with connectors identical to the NES. Its second controller was the same as the first, with Select and Start present, and no microphone.<br />
<br />
The expansion port of the Famicom could be used to connect external controllers. These gave the same standard 8-bit report, but through D1 instead of D0. It was common for Famicom games to combine D1 and D0 (logical OR) when reading to permit players to use expansion controllers instead, though several games do not support this<ref>[https://www.famicomworld.com/forum/index.php?topic=6701.msg167005#msg167005 Famicom World forum post]: Famicom games that do not work with pads connected through the expansion port.</ref>. Alternatively, these could be used as extra controllers for [[Four Score|4-player]] games.<br />
<div style="clear: both"></div><br />
<br />
== Hardware ==<br />
<br />
The [https://www.ti.com/lit/ds/symlink/cd4021b-q1.pdf 4021] (or [http://www.datasheetcatalog.org/datasheet/philips/74HC_HCT165_CNV_2.pdf 74LS165]) IC is an 8-bit parallel-to-serial shift<br />
register. It has a pin "serial input", ordinarily used to chain the output of one shift register into the next one as seen in the Four Score or the Super NES controller. The serial input on the tail end of such a chain (or the only one in the case of an NES) can be tied to ground or Vcc, which determines the state of the output after all bits have been shifted out. If this is grounded, the shift register produces a 0 after all bits have been shifted out; if it's tied to Vcc, it produces a 1.<br />
<br />
The 4021 has a parallel/serial control pin connected to ''[[Controller port pinout|OUT0]]'' ($4016 bit 0). When this goes high (parallel mode), the current controller state is directly captured by the 8 bits of its shift register. When it returns to low (serial mode) the bits in the register will be shifted once for every rising edge of ''CLK''. CLK is normally high, but goes low before the read from $4016 or $4017, then returns high after the read, creating the rising edge that will shift the next bit into place.<br />
<br />
In the NES controller, this input is grounded. But because the signals from the controllers pass through an inverter before reaching the CPU, the register produces a 1 for all reads after the first eight.<br />
<br />
If using DPCM audio samples, read conflicts may occur requiring a software technique to correct for them. See: [[Controller reading#DPCM conflict|Controller reading: DPCM conflict]].<br />
<br />
=== PAL ===<br />
<br />
Some PAL region consoles have internal diodes on their controller port. (See: [[Controller port pinout#PAL|Controller port pinout: PAL]])<br />
<br />
These diodes prevent the Clock and Latch signals from functioning unless they are pulled high. PAL controllers for these regions (NES-004) each contain a 3.6KΩ resistor between these two inputs and 5V.<ref>[//forums.nesdev.org/viewtopic.php?p=238272#p238272 Forum post]: explaining PAL controller diodes and their function.</ref><br />
<br />
On these systems, only PAL controllers with the pull-ups can be read. NTSC systems can read controllers of either type. Modifying the internal controller port to bypass these diodes will make the PAL system compatible with both. Conversely, modifying a controller to add the pull-up resistors makes it compatible with both types of systems.<br />
<br />
== Turbo ==<br />
<br />
A '''turbo controller''' such as the NES Max or NES Advantage is read just like a standard controller, but the user can switch some of its buttons to be toggled by an oscillator.<br />
Such an oscillator turns the button on and off at 15 to 30 Hz, producing rapid fire in games.<br />
<br />
A controller should not toggle the button states on each strobe pulse.<br />
Doing so will cause problems for games that poll the controller in a loop until they get two identical consecutive reads (see DMC conflict above). The game may halt while the turbo button is held, or crash, or cause other unknown behaviour.<br />
<br />
== See also ==<br />
*[[Controller reading]]<br />
*[[Controller detection]]<br />
*[[Controller port pinout]]<br />
*[[Four Score]] 4-player adapter<br />
*[[SNES controller]] has backward compatible protocol with the NES<br />
<br />
== References ==<br />
<references/><br />
* [//forums.nesdev.org/viewtopic.php?f=9&t=8848 Forum post:] Famicom controller PCB and exterior photographs<br />
<br />
[[Category:Controllers]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Nintendo-Famicom-Controller-II-FL.jpg&diff=21544File:Nintendo-Famicom-Controller-II-FL.jpg2024-01-18T04:30:48Z<p>Fiskbit: The standard second-player Famicom controller, which omits start and select buttons but features a microphone with volume slider.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The standard second-player Famicom controller, which omits start and select buttons but features a microphone with volume slider.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:NES-Controller-Flat.jpg&diff=21543File:NES-Controller-Flat.jpg2024-01-18T04:26:34Z<p>Fiskbit: The standard NES controller.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The standard NES controller.<br />
<br />
Image by Evan Amos <br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Game_Genie&diff=21542Game Genie2024-01-17T18:27:33Z<p>Fiskbit: Adds a Game Genie image.</p>
<hr />
<div>[[File:Game-Genie-NES.jpg|200px|thumb|right|Game Genie]]<br />
The '''Game Genie''' is a enhancement cart for the NES designed by [[wikipedia:Camerica|Camerica]] and distributed by [[wikipedia:Galoob|Galoob]] and Camerica. It functions as a pass-thru, with a [[Cartridge_connector#Pinout_of_72-pin_NES_consoles_and_cartridges|72-pin cartridge connector]] connecting it to the NES, and a 72-pin cartridge slot for a game to be inserted into. When plugged in between a game and the NES and turned on, it provides a simple interface to enter up to three cheat codes, which then modify the behavior of the game.<br />
First revision were build using [[NES_Game_Genie_IC_pinout|ASIC blob chip]] and 4 kB ROM, the latter one has both chips integrated into single epoxy blob. There even exist a console (''Geniecom Enhance Console video Game'') that has the Game Genie ASIC DIP CHIP (''GENIECOM-V1 BIC'') built it.<br />
<br />
The Game Genie is not assigned a [[mapper]] number.<br />
<br />
[[File:Game_Genie_Revision_1.5A_(PCB_Front).jpg|thumb|PCB Front]]<br />
[[File:Game_Genie_Revision_1.5A_(PCB_Back).jpg|thumb|PCB Back]]<br />
[[File:game_genie_blob_top.jpg|thumb|Blob Top]]<br />
[[File:game_genie_blob_bottom.jpg|thumb|Blob Bottom]]<br />
<br />
== Technical ==<br />
<br />
The Game Genie works by intercepting CPU reads and replacing the game cart's response with its own response. It can intercept any three addresses in CPU $8000…$FFFF and respond with a single replacement for each. To make the tool more compatible with [[Glossary#B|bank-switching]], each of the three codes has an optional compare value which can be used to only replace the byte if the original byte matches the compare, hopefully limiting the cheat to functioning on the desired bank.<br />
<br />
When first booted, the Game Genie presents its own 4-KiB [[Glossary#P|PRG ROM]] (mapped at $c000-$ffff and mirrored 4 times; $8000-$bfff is open bus) and a series of simple gates masquerading as a [[Glossary#C|CHR ROM]]. The included PRG ROM runs code to show a simple code entry user interface. When the user presses Start, the cheat values are written to memory-mapped registers, and then another register is written which switches the Game Genie into game mode, where the attached game cart's CHR and PRG is passed through, save whatever code replacements were defined. The Game Genie remains in game mode until power-cycled, and will respond to no further writes.<br />
<br />
== Software version ==<br />
The only version known to exists is 1.5A (CRC32 = 1A3A22A1), present both in DIP chip version (with ROM chip marked as '''GENIE V1.5A''') and single epoxy blob one).<br />
<br />
<br />
== Registers ==<br />
<br />
=== Master Control ($8000) ===<br />
7 bit 0<br />
---- ----<br />
.DDD CCCE<br />
||| ||||<br />
||| |||+- Write 1 to switch into game mode<br />
||| +++-- Compare enable for each of the three codes<br />
+++------ Disable each of the three codes<br />
<br />
Bit 1 and 4 correspond to the code at $8001…$8004.<br />
<br />
Game Genie writes first a value with bit 0 set and then writes 0x00 to this register. Because after the first write, the Game Genie logic switches into game mode, any further writes to range $8000–$ffff will cause the slave cartridge /ROMSEL to become low for that write cycle. As a result, the second write will be seen and interpreted by the hardware inside slave game cartridge.<br />
The reason for this write is unknown, maybe it initializes the bank select register for MMC3 games?<br />
<br />
=== Address High ($8001, $8005, $8009) ===<br />
7 bit 0<br />
---- ----<br />
.AAA AAAA<br />
||| ||||<br />
+++-++++- Bits 8:14 of address for this cheat (bit 15 fixed to 1)<br />
<br />
=== Address Low ($8002, $8006, $800A) ===<br />
7 bit 0<br />
---- ----<br />
AAAA AAAA<br />
|||| ||||<br />
++++-++++- Bits 0:7 of address for this cheat<br />
<br />
=== Compare ($8003, $8007, $800B) ===<br />
7 bit 0<br />
---- ----<br />
CCCC CCCC<br />
|||| ||||<br />
++++-++++- Compare value for this cheat (write 0 if unused?)<br />
<br />
=== Replace ($8004, $8008, $800C) ===<br />
7 bit 0<br />
---- ----<br />
RRRR RRRR<br />
|||| ||||<br />
++++-++++- Replacement value for this cheat<br />
<br />
=== Unknown ($FFF0, $FFF1) ===<br />
The Game Genie rom writes 0 to $FFF0, $FFF1, $FFF0 in that sequence.<br />
<br />
== Pattern Tables ==<br />
<br />
When game mode is inactive, the Game Genie generates [[PPU pattern tables]] through PPU $0000…$1FFF by the following method:<br />
<br />
* When PPU <tt>A2</tt> = 1:<br />
** PPU <tt>A4</tt> → PPU <tt>D4</tt>…<tt>D7</tt><br />
** PPU <tt>A5</tt> → PPU <tt>D0</tt>…<tt>D3</tt><br />
* When PPU <tt>A2</tt> = 0:<br />
** PPU <tt>A6</tt> → PPU <tt>D4</tt>…<tt>D7</tt><br />
** PPU <tt>A7</tt> → PPU <tt>D0</tt>…<tt>D3</tt><br />
<br />
This creates 16 distinct objects that are used to build the menu graphics:<br />
<br />
[[File:Gg sprites.PNG]]<br />
<br />
== Bugs ==<br />
Because of how the hardware is designed, there are some bugs or limitations of this device:<br />
* When a cartridge has something mapped at $4020–$7FFF (WRAM, PRG ROM) and a code for region $C020–$FFFF is added, the Game Genie will hold the slave cartridge's /ROMSEL at 1 when reading from that location. But then, the cartridge logic will see this read cycle as something below $8000, enabling the chip that is mapped here, causing bus conflict at this location and resulting in invalid data being returned to the CPU.<ref name="p230447">[https://forums.nesdev.org/viewtopic.php?p=230447#p230447 Forums: Game Genie - does it work for $e000-$ffff + WRAM?]</ref> Some codes rely on these bus conflicts. For example, in The Legend of Zelda, the code XYYYYL causes the sword beam to leave bait behind, but crashes instead if bus conflicts are not emulated.<br />
* Cartridges that rely only on PPU /A13 when decoding CHR-ROM (like MMC5) will not display the the Game Genie menu properly, as the Game Genie ignores this line, causing bus conflict.<ref name="p230447"/><br />
* According to the Game Genie patent, the process of determining if a code with comparison should be enabled is asynchronous. This makes it impossible to apply multiple codes with the same address but different replace/compare values. The Game Genie allows entering such codes, but when it comes to sending them to the ASIC chip, only the first such code will be enabled.<br />
<br />
== References ==<br />
<br />
<references/><br />
<br />
== External links ==<br />
<br />
* [http://nesdev.org/nesgg.txt nesgg.txt] – ''NES Game Genie Code Format DOC v0.71'' by Benzene of Digital Emutations, 1997-07-10<br />
* [http://patents.google.com/patent/US5112051A/en Patent US5112051A – ''Interfacing device for a computer games system'']<br />
* [https://www.kevinselwyn.com/posts/game-genie-disassembly/ NES Game Genie ROM disassembly] by Kevin Selwyn ([http://github.com/kevinselwyn/game-genie-disassembly GitHub page])<br />
* [http://github.com/qalle2/nes-gg-disassembly NES Game Genie ROM disassembly] by qalle</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Game-Genie-NES.jpg&diff=21541File:Game-Genie-NES.jpg2024-01-17T18:24:57Z<p>Fiskbit: The Galoob Game Genie, a pass-through cartridge that can modify cartridge ROM values to alter game behavior.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The Galoob Game Genie, a pass-through cartridge that can modify cartridge ROM values to alter game behavior.<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=PPU_rendering&diff=21540PPU rendering2024-01-17T17:58:09Z<p>Fiskbit: Adds formatting that ensures the priority table never hangs into the next section.</p>
<hr />
<div>== Drawing overview ==<br />
The PPU outputs a picture region of 256x240 pixels and a border region extending 16 pixels left, 11 pixels right, and 2 pixels down (283x242). The picture region is generated by doing memory fetches that fill shift registers, from which a pixel is selected. It is composed of a background region filling the entire screen and smaller sprites that may be placed nearly anywhere on it. In the border and any transparent pixel, the PPU displays the palette index selected by the PPU's EXT input, which is grounded to index 0 in stock consoles.<br />
<br />
=== Picture region ===<br />
[BBBBBBBB] - Next tile's pattern data,<br />
[BBBBBBBB] - 2 bits per pixel<br />
||||||||<----[Transfers every inc hori(v)]<br />
vvvvvvvv<br />
Serial-to-parallel - [AAAAAAAA] <- [BBBBBBBB] <- [1...] - Parallel-to-serial<br />
shift registers - [AAAAAAAA] <- [BBBBBBBB] <- [1...] - shift registers<br />
vvvvvvvv<br />
|||||||| [Sprites 0..7]----+ [EXT in]----+<br />
|||||||| | |<br />
[fine_x selects a bit]---->[ Mux ]------------>[Priority mux]----->[Mux]---->[Pixel]<br />
|||||||| |<br />
^^^^^^^^ +------------>[EXT out]<br />
Serial-to-parallel - [PPPPPPPP] <- [P] - 1-bit latch<br />
shift registers - [PPPPPPPP] <- [P] - 1-bit latch<br />
^<br />
|<--------[Transfers every inc hori(v)]<br />
[ Mux ]<----[coarse_x bit 1 and coarse_y bit 1 select 2 bits]<br />
||||||||<br />
^^^^^^^^<br />
[PPPPPPPP] - Next tile's attributes data<br />
<br />
To generate the background in the picture region, the PPU performs memory fetches on dots 321-336 and 1-256 of scanlines 0-239 and 261. Each memory fetch takes 2 dots: on the 1st, the full address is placed onto the PPU's address bus and the low 8 bits are stored into an external address latch, and on the 2nd, the read is performed. Fetches require 2 dots because the same physical pins are used for the data bus and low 8 bits of address, so the address must be latched externally before a read can be done.<br />
<br />
In each 8-dot window, the PPU performs the 4 memory fetches required to produce 8 pixels, fully occupying the PPU bus. Using the current scroll register, v, to produce the target addresses, the PPU fetches a tile ID from the nametable, attributes data from the attributes table, and the low and then high bitplane of the pattern data for that tile ID. The fetched bytes are stored in internal registers.<br />
<br />
On every 8th dot in these background fetch regions (the same dot on which the coarse x component of v is incremented), the pattern and attributes data are transferred into registers used for producing pixel data. For the pattern data, these transfers are into the high 8 bits of two 16-bit shift registers. For the attributes data, only 2 bits are transferred and into two 1-bit latches that feed 8-bit shift registers. The concept for both is the same, differing merely because the attributes data is the same for all 8 pixels, negating the need to store 8 copies of it.<br />
<br />
On every dot in these background fetch regions, a 4-bit pixel is selected by the fine x register from the low 8 bits of the pattern and attributes shift registers, which are then shifted.<br />
<br />
The PPU then selects between this background pixel and the 4-bit sprite pixel produced by the OAM process. This selection depends on whether each pixel is transparent (low 2 bits are both 0) and the sprite's priority (whether it appears in front of (0) or behind (1) the background). If both are transparent, the background pixel is selected. After the selection, the pixel is now 5-bit, with the new top bit determined by whether background (0) or sprites (1) was selected. If the PPU is configured to output on its EXT pins, it outputs the low 4 bits of the selected pixel.<br />
<br />
If the selected pixel is transparent, it is replaced with the EXT input: bit 4 is always 0, and bits 3-0 take the values of EXT3-0. The PPU's 4 EXT pins are grounded in all known console variations, so this input is normally 0. If the PPU is configured for EXT output, then the input value is always 0. (However, because these pins are grounded, EXT should never be in output mode because it could cause physical damage.)<br />
<br />
The result of all of this is a 5-bit index used to look up a value from palette RAM. This value is a color, which can be modified by the emphasis and greyscale features of the [[PPUMASK]] register and is then drawn as a pixel.<br />
<br />
As-used, EXT input always produces an all-0 value, so transparent pixels always display the color at $3F00 in palette RAM, referred to as the 'backdrop' color.<br />
<br />
{| class="wikitable floatright"<br />
|+ Priority multiplexer decision table<br />
! BG pixel || Sprite pixel || Priority || Output<br />
|-<br />
| 0 || 0 || X || EXT in ($3F00)<br />
|-<br />
| 0 || 1-3 || X || Sprite<br />
|-<br />
| 1-3 || 0 || X || BG<br />
|-<br />
| 1-3 || 1-3 || 0 || Sprite<br />
|-<br />
| 1-3 || 1-3 || 1 || BG<br />
|}<br />
<br />
Notes:<br />
* Sprite have a 1-bit priority relative to backgrounds, but they also have a priority relative to each other depending on their order in OAM. Lower sprite indices are higher priority than higher indices, and the highest priority sprite pixel is selected before background priority is handled. Because of this, a high priority sprite in the background takes precedence over a lower priority sprite even in the foreground, which can cause the background to appear in front of that foreground sprite, referred to as the [[PPU_sprite_priority|sprite priority quirk]].<br />
* Reads come from an address composed of the latched low 8 bits and the current high 6 bits. If rendering is toggled, these can become desynced, producing a hybrid address sourced from two different addresses and reading from an address the PPU itself never actually outputted.<br />
* The 16-bit pattern shift registers shift in 1's. Normally, these are clobbered by the next pattern data load, but toggling rendering mid-frame may allow more than 8 shifts between loads, allowing these 1's to be rendered.<br />
* The storage registers, shift registers, and 1-bit latches described here decay to 0 on a time scale of probably around 2 frames. The results of this decay may be visible when turning rendering on mid-frame.<br />
* Bits leaving the attributes and low pattern data registers are inverted, and then inverted back before the background/sprite priority mux. Because of this, if they decay to 0, they actually end up as 1's in the output, and any 1's resulting from extra shifts in the low pattern shift register end up as 0's.<br />
<div style="clear: both"></div><br />
<br />
=== Border region ===<br />
The border region displays the palette RAM entry selected by EXT input, either the data on the EXT pins if in input mode or 0 if in output mode. The first pixel on the left border is displayed with greyscale mode enabled. The border is affected by [[PPUMASK]] emphasis and greyscale effects.<br />
<br />
=== Rendering disabled ===<br />
With rendering disabled, both the picture and border regions display only EXT input. On PPUs that support CPU reads from palette RAM (RP2C02G, RP2C02H), the automatic greyscale effect on the first border pixel is disabled if a CPU palette read occurs at the exact same time.<ref>[https://forums.nesdev.org/viewtopic.php?p=265093#p265093 Forum post:] Fiskbit's greyscale_column_sparkle_test</ref><br />
<br />
When the PPU isn't rendering, its v register specifies the current VRAM address (and is output on the PPU's address pins). Whenever the low 14 bits of v point into palette RAM ($3F00-$3FFF), the PPU will continuously draw the color at that address instead of the EXT input, overriding the backdrop color. This is because the only way to access palette RAM is with this drawing mechanism, and is akin to color RAM dots on consoles such as the Master System and Mega Drive / Genesis. Backdrop override is used intentionally by some software.<br />
<br />
[[PPUMASK]] emphasis and greyscale effects apply even with rendering disabled.<br />
<br />
=== PAL ===<br />
PAL PPUs have the same rendering behavior as NTSC PPUs except for the border. The border is always black and extends 1 pixel into the top and 2 pixels into each of the left and right edges of the picture region, whether rendering is enabled or not. Emphasis and greyscale effects do not apply to this border. Note that this border does not change the behavior of sprite 0 hit compared to NTSC.<br />
<br />
== Line-by-line timing ==<br />
The PPU renders 262 scanlines per frame. Each scanline lasts for 341 PPU clock cycles (113.667 CPU clock cycles; 1 CPU cycle = 3 PPU cycles), with each clock cycle producing one pixel. The line numbers given here correspond to how the internal PPU frame counters count lines.<br />
<br />
The information in this section is summarized in the diagram in the next section.<br />
<br />
The timing below is for NTSC PPUs. PPUs for 50 Hz TV systems [[Cycle_reference_chart#Clock_rates|differ]]:<br />
* Dendy PPUs render 51 post-render scanlines instead of 1<br />
* PAL NES PPUs render 70 vblank scanlines instead of 20, and they additionally run '''3.2''' PPU cycles per CPU cycle, or 106.5625 CPU clock cycles per scanline.<br />
<br />
=== Pre-render scanline (-1 or 261) ===<br />
This is a dummy scanline, whose sole purpose is to fill the shift registers with the data for the first two tiles of the next scanline. Although no pixels are rendered for this scanline, the PPU ''still'' makes the same memory accesses it would for a regular scanline, using whatever the current value of the PPU's [[PPU_scrolling#PPU_internal_registers|V register]] is, and for the sprite fetches, whatever data is currently in secondary OAM (e.g., the results from scanline 239's [[PPU_sprite_evaluation|sprite evaluation]] from the previous frame).<br />
<br />
This scanline varies in length, depending on whether an even or an odd frame is being rendered. For odd frames, the cycle at the end of the scanline is skipped (this is done internally by jumping directly from (339,261) to (0,0), replacing the idle tick at the beginning of the first visible scanline with the last tick of the last dummy nametable fetch). For even frames, the last cycle occurs normally. This is done to compensate for some shortcomings with the way the PPU physically outputs its video signal, the end result being a crisper image when the screen isn't scrolling. However, this behavior can be bypassed by keeping rendering disabled until after this scanline has passed, which results in an image with a "dot crawl" effect similar to, but not exactly like, what's seen in interlaced video.<br />
<br />
During pixels 280 through 304 of this scanline, the vertical scroll bits are reloaded if rendering is enabled.<br />
<br />
=== Visible scanlines (0-239) ===<br />
These are the visible scanlines, which contain the graphics to be displayed on the screen. This includes the rendering of both the background and the sprites. During these scanlines, the PPU is busy fetching data, so the program should ''not'' access PPU memory during this time, [[PPU_registers#Mask_.28.242001.29_.3E_write|unless rendering is turned off]].<br />
<br />
==== Cycle 0 ====<br />
<br />
This is an idle cycle. The value on the PPU address bus during this cycle appears to be the same CHR address that is later used to fetch the low background tile byte starting at dot 5 (possibly calculated during the two unused NT fetches at the end of the previous scanline).<br />
<br />
==== Cycles 1-256 ====<br />
The data for each tile is fetched during this phase. Each memory access takes 2 PPU cycles to complete, and 4 must be performed per tile:<br />
#Nametable byte<br />
#Attribute table byte<br />
#Pattern table tile low<br />
#Pattern table tile high (+8 bytes from pattern table tile low)<br />
<br />
The data fetched from these accesses is placed into internal latches, and then fed to the appropriate shift registers when it's time to do so (every 8 cycles). Because the PPU can only fetch an attribute byte every 8 cycles, each sequential string of 8 pixels is forced to have the same palette attribute.<br />
<br />
Sprite 0 hit acts as if the image starts at cycle 2 (which is the same cycle that the shifters shift for the first time), so the sprite 0 flag will be raised at this point at the earliest. Actual pixel output is delayed further due to internal render pipelining, and the first pixel is output during cycle 4.<br />
<br />
The shifters are reloaded during ticks 9, 17, 25, ..., 257.<br />
<br />
'''Note:''' At the beginning of each scanline, the data for the first two tiles is already loaded into the shift registers (and ready to be rendered), so the first tile that gets fetched is Tile 3.<br />
<br />
While all of this is going on, [[PPU_sprite_evaluation|sprite evaluation]] for the ''next'' scanline is taking place as a seperate process, independent to what's happening here.<br />
<br />
==== Cycles 257-320 ====<br />
The tile data for the sprites on the ''next'' scanline are fetched here. Again, each memory access takes 2 PPU cycles to complete, and 4 are performed for each of the 8 sprites:<br />
#Garbage nametable byte<br />
#Garbage nametable byte<br />
#Pattern table tile low<br />
#Pattern table tile high (+8 bytes from pattern table tile low)<br />
<br />
The garbage fetches occur so that the same circuitry that performs the BG tile fetches could be reused for the sprite tile fetches.<br />
<br />
If there are less than 8 sprites on the next scanline, then dummy fetches to tile $FF occur for the left-over sprites, because of the dummy sprite data in the secondary OAM (see [[PPU_sprite_evaluation|sprite evaluation]]). This data is then discarded, and the sprites are loaded with a transparent set of values instead.<br />
<br />
In addition to this, the X positions and attributes for each sprite are loaded from the secondary OAM into their respective counters/latches. This happens during the second garbage nametable fetch, with the attribute byte loaded during the first tick and the X coordinate during the second.<br />
<br />
==== Cycles 321-336 ====<br />
This is where the first two tiles for the ''next'' scanline are fetched, and loaded into the shift registers. Again, each memory access takes 2 PPU cycles to complete, and 4 are performed for the two tiles:<br />
#Nametable byte<br />
#Attribute table byte<br />
#Pattern table tile low<br />
#Pattern table tile high (+8 bytes from pattern table tile low)<br />
<br />
==== Cycles 337-340 ====<br />
Two bytes are fetched, but the purpose for this is unknown. These fetches are 2 PPU cycles each.<br />
#Nametable byte<br />
#Nametable byte<br />
Both of the bytes fetched here are the same nametable byte that will be fetched at the beginning of the next scanline (tile 3, in other words).<br />
At least one mapper -- [[MMC5]] -- is known to use this string of three consecutive nametable fetches to clock a scanline counter.<br />
<br />
=== Post-render scanline (240) ===<br />
The PPU just idles during this scanline. Even though accessing PPU memory from the program would be safe here, the VBlank flag isn't set until ''after'' this scanline.<br />
<br />
=== Vertical blanking lines (241-260) ===<br />
The VBlank flag of the PPU is set at tick 1 (the ''second'' tick) of scanline 241, where the VBlank NMI also occurs. The PPU makes no memory accesses during these scanlines, so PPU memory can be freely accessed by the program.<br />
<br />
== PPU address bus contents ==<br />
<br />
During frame rendering, provided rendering is enabled (i.e., when either background or sprite rendering is enabled in [[PPU registers|$2001:3-4]]), the value on the PPU address bus is as indicated in the descriptions above and in the frame timing diagram below. During VBlank and when rendering is disabled, the value on the PPU address bus is the current value of the [[PPU scrolling|v]] register.<br />
<br />
To save pins, the PPU multiplexes the lower eight VRAM address pins, also using them as the VRAM data pins. This leads to each VRAM access taking two PPU cycles:<br />
# During the first cycle, the entire VRAM address is output on the PPU address pins and the lower eight bits stored in an external octal latch by asserting the ALE (Address Latch Enable) line. (The octal latch is the lower chip to the right of the PPU in [[media:neswires.jpg|this wiring diagram]].)<br />
# During the second cycle, the PPU only outputs the upper six bits of the address, with the octal latch providing the lower eight bits (VRAM addresses are 14 bits long). During this cycle, the value is read from or written to the lower eight address pins.<br />
<br />
As an example, the PPU VRAM address pins will have the value $2001 followed by the value $20AB for a read from VRAM address $2001 that returns the value $AB.<br />
<br />
== Frame timing diagram ==<br />
<br />
[[File:Ppu.svg|662px|none|thumb|NTSC timing diagram]]<br />
<br />
== See also ==<br />
* [[Nametable]]<br />
* [[Attribute table]]<br />
* [[NTSC video]]<br />
* [[PPU frame timing]]<br />
* [[PPU sprite evaluation]]<br />
<br />
= References =<br />
:*[http://nesdev.org/2C02%20technical%20reference.TXT NTSC 2C02 technical reference]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Four_player_adapters&diff=21539Four player adapters2024-01-17T17:56:57Z<p>Fiskbit: Adds an NES Satellite image.</p>
<hr />
<div>Four player adapters are devices that plug into controller or expansion ports and provide additional ports. These ports can be used as alternatives to hardwired controllers or for multiplayer with more than 2 simultaneous players. Contemporary adapters allow some consoles to interface with up to 8 controllers. These adapters come in multiple forms, each with their own interfaces and limitations.<br />
<br />
=Adapters=<br />
<br />
=="Simple" Famicom adapters==<br />
Because the Famicom only has one expansion port, a device such as the '''JoyPair''' or '''Twin Adapter''' is required to attach multiple controllers to it. Standard expansion controllers respond on D1 of $4016, and these multi-port devices redirect the second port to D1 of $4017. These may be used as players 3 and 4. In 1- or 2-player games for the Famicom, though, it is common to OR together the D1 and D0 bits of a joypad read to allow players to use external controllers as substitutes for the hardwired ones.<br />
<br />
The expansion ports on these multi-port devices do not pass through all of the signals and thus are limited in functionality compared to the console's expansion port. Because of this, many controllers are not compatible with these adapters.<br />
<br />
=== Pinout ===<br />
JoyPair CN1 | | Famicom EXP<br />
-----------------+--+-----------------<br />
GND 01 |--| 01 GND<br />
OUT0 12 |<-| 12 OUT0<br />
Joypad 1 /D1 13 |->| 13 Joypad 1 /D1<br />
Joypad 1 /OE 14 |<-| 14 Joypad 1 /OE<br />
5V 15 |--| 15 5V<br />
<br />
JoyPair CN2 | | Famicom EXP<br />
-----------------+--+-----------------<br />
GND 01 |--| 01 GND<br />
OUT0 12 |<-| 12 OUT0<br />
Joypad 1 /D1 13 |->| 07 Joypad 2 /D1<br />
Joypad 1 /OE 14 |<-| 09 Joypad 2 /OE<br />
5V 15 |--| 15 5V<br />
<br />
(All other JoyPair pins not connected)<br />
<br />
==Hori 4 Players Adapter==<br />
<br />
The '''Hori 4 Players Adapter''' is a Famicom expansion port device that provides 4 ports, usable in 2- and 4-controller modes selected using a switch. In 2-controller mode, ports 1 and 2 on the adapter function exactly like a "simple" Famicom adapter, and ports 3 and 4 are disabled. In 4-controller mode, ports 1 and 3 are multiplexed onto $4016 D1 and ports 2 and 4 onto $4017 D1. The first 8 reads from an address provide the joypad 1 D1 report from the first controller, the next 8 reads the joypad 1 D1 report from the second controller, and the next 8 reads a signature unique to that address. The read counter is reset as long as OUT0 is 1. The same connection limitations of the "simple" adapters still apply in 4-controller mode, which combined with the 8 read limit restricts the set of usable contemporary controllers to those compatible with the standard controller.<br />
<br />
===Protocol===<br />
==== Input ($4016 write) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxS<br />
|<br />
+- Controller read strobe<br />
<br />
This matches the normal strobe behavior used by the [[Standard_controller#Input_.28.244016_write.29|standard controller]] and strobes all 4 at once.<br />
<br />
==== Output ($4016/$4017 read) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxDx<br />
|<br />
+-- Serial controller data<br />
<br />
==== Report ====<br />
<br />
$4016 read D1:<br />
0-7 - Joypad 1 D1 bits 0-7 from controller #1<br />
8-15 - Joypad 1 D1 bits 0-7 from controller #3<br />
16-17 - (Always 0)<br />
18 - (Always 1)<br />
19-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
$4017 read D1:<br />
0-7 - Joypad 1 D1 bits 0-7 from controller #2<br />
8-15 - Joypad 1 D1 bits 0-7 from controller #4<br />
16-18 - (Always 0)<br />
19 - (Always 1)<br />
20-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
Note: ''Joypad 1'' and ''joypad 2'' are names used on the controller-side [[Expansion_port#Famicom|Famicom expansion port]] pin interface, as compared to $4016 and $4017 on the CPU side. While joypad 1 normally connects to $4016, this adapter routes each controller's joypad 1 /D1 to $4016 or $4017 as needed.<br />
<br />
==Four Score==<br />
<br />
The Four Score is an adapter that plugs into both NES controller ports and provides 4 ports, usable in 2- and 4-controller modes. This device is nearly identical to the Hori 4 Players Adapter, differing in that D0 is used instead of D1 and the addresses' signatures are swapped. This device also provides two turbo switches.<br />
<br />
===Protocol===<br />
==== Input ($4016 write) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxS<br />
|<br />
+- Controller read strobe<br />
<br />
This matches the normal strobe behavior used by the [[Standard_controller#Input_.28.244016_write.29|standard controller]] and strobes all 4 at once.<br />
<br />
==== Output ($4016/$4017 read) ====<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxxD<br />
|<br />
+- Serial controller data<br />
<br />
==== Report ====<br />
<br />
$4016 read D0:<br />
0-7 - Joypad D0 bits 0-7 from controller #1<br />
8-15 - Joypad D0 bits 0-7 from controller #3<br />
16-18 - (Always 0)<br />
19 - (Always 1)<br />
20-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
$4017 read D0:<br />
0-7 - Joypad D0 bits 0-7 from controller #2<br />
8-15 - Joypad D0 bits 0-7 from controller #4<br />
16-17 - (Always 0)<br />
18 - (Always 1)<br />
19-23 - (Always 0)<br />
<br />
24+ - (Always 1)<br />
<br />
Note: ''Joypad D0'' refers to the data normally available on $4016 or $4017 bit 0. Unlike the Famicom expansion port, NES controller port wiring is relative to the port used, so while a controller normally chooses which data inputs to use, it does not choose whether those are joypad 1 or joypad 2.<br />
<br />
===Turbo===<br />
<br />
The Four Score includes separate turbo enables intended for the A and B buttons. Each of these applies universally to all attached controllers and in both 2- and 4-controller modes. These turbos force their respective bits to 0 at a fixed rate by ANDing with a mask that alternates between 0 and 1, making a held button appear as though it is being rapidly pressed and released. After a strobe, the A turbo applies to the first read of each controller's report and the B turbo to the second read. In 2-controller mode, each turbo also applies again after every 32 additional reads, causing toggles in the stream of 1's that follow the report from official controllers.<br />
<br />
The toggle rate is based on the Four Score's internal clock and is approximately 2 frames.<br />
<br />
==NES Satellite==<br />
<br />
[[File:NES-Satellite.jpg|200px|thumb|right|top|NES Satellite]]<br />
The NES Satellite is a 4-controller wireless adapter similar to the Four Score. Specific details are not yet known. Instead of a mode switch for 2 or 4 controllers, the NES Satellite has a mode switch selecting between standard controllers and the Zapper. Like the Four Score, it also features A and B turbo switches.<br />
<div style="clear: both"></div><br />
<br />
=Hardware=<br />
<br />
Inside the Four Score and 4 Players Adapter is a 22-pin DIP labeled [[FPA-PAL-S01 pinout|FPA-S01]]. This IC consists of a decoder and one set of shift register, 5-bit counter, and multiplexer per joypad address, allowing each address to return the 8-bit contents of joypads 1 and 3 or 2 and 4 in series, followed by the signature byte.<br />
<br />
In case you want to build a four player adapter into an arcade cabinet or some other permanent installation, you don't need to use a Four Score or other adapter: you just need six total shift registers. The inputs to these shift registers are parallel, so you need separate wires for each signal, like from SMS or ZX Spectrum controllers.<br />
<br />
=5+ controllers=<br />
<br />
These adapters can be used in combination with each other on the AV Famicom for up to 8 controllers, or on the Famicom with the hardwired controllers for up to 6. Because nonstandard controllers are not compatible with 4-controller modes, using them reduces the maximum possible controller count, but if a single nonstandard controller such as a mouse is desired, it can be used with a "simple" adapter alongside up to 6 standard controllers on an AV Famicom using a Four Score in the NES controller ports, a "simple" adapter in the expansion port, and a Hori 4 Players Adapter with controllers in ports 1 and 3 in the other "simple" adapter port.<br />
<br />
=Compatible Games=<br />
<br />
Games known to support 3 or more simultaneous controllers:<br />
{| class="sortable wikitable"<br />
! Game !! Hori 4-player Adapter !! Four Score !! Simple<br />
|-<br />
| A Nightmare on Elm Street || yes || yes || ?<br />
|-<br />
| Bomber Man II (J) || no || no || yes<br />
|-<br />
| Bomberman II (U) || no || yes || ?<br />
|-<br />
| Downtown Nekketsu Koushinkyoku: Soreyuke Daiundoukai || yes || yes || yes<br />
|-<br />
| Gauntlet II || no || yes || no<br />
|-<br />
| Greg Norman's Golf Power || yes || yes || ?<br />
|-<br />
| Harlem Globetrotters || no || yes || ?<br />
|-<br />
| Ike Ike! Nekketsu Hockey Bu: Subette Koronde Dai Rantou || no || ? || yes<br />
|-<br />
| Indy Heat || yes || yes || ?<br />
|-<br />
| Kings of the Beach || yes || yes || ?<br />
|-<br />
| Kunio-kun no Nekketsu Soccer League || no || unlikely || yes<br />
|-<br />
| M.U.L.E. || no || yes || ?<br />
|-<br />
| Magic Johnson's Fast Break || yes || yes || ?<br />
|-<br />
| Millionaire (Sachen) || no || no || yes<br />
|-<br />
| Moero TwinBee: Cinnamon-hakase o Sukue! || no || ? || yes<br />
|-<br />
| Monster Truck Rally || no || yes || ?<br />
|-<br />
| NES Play Action Football || yes || yes || ?<br />
|-<br />
| Nekketsu Kakutou Densetsu || no || ? || yes<br />
|-<br />
| Nekketsu Koukou Dodge Ball Bu || no || ? || yes<br />
|-<br />
| Nekketsu Street Basket: Ganbare Dunk Heroes || no || ? || yes<br />
|-<br />
| Nintendo World Cup (U) || yes || yes || ?<br />
|-<br />
| R.C. Pro-Am II || yes || yes || ?<br />
|-<br />
| Rackets and Rivals || no || yes || ?<br />
|-<br />
| Roundball: 2-on-2 Challenge || no || yes || ?<br />
|-<br />
| Smash T.V. (twin-stick for 2 players) || no || yes || ?<br />
|-<br />
| Spot || yes || yes || no<br />
|-<br />
| Super Jeopardy! || yes || yes || ?<br />
|-<br />
| Super Off Road || yes || yes || no<br />
|-<br />
| Super Spike V'Ball || everywhere but title screen || everywhere but title screen || yes<br />
|-<br />
| Swords and Serpents || no || yes || ?<br />
|-<br />
| Top Players' Tennis || yes || yes || ?<br />
|-<br />
| U.S. Championship V'Ball || only during 3+player gameplay || only during 3+player gameplay || yes<br />
|-<br />
| Wit's || yes || yes || yes<br />
|}<br />
<br />
Homebrew games:<br />
*''Double Action Blaster Guys'' becomes ''Quadruple Action Blaster Guys'' when Four Score is connected (NES)<br />
*''Micro Mages'' (NES and Famicom)<br />
*''NESert Golfing'' (NES and Famicom)<br />
*''Spacey McRacey'' (NES)<br />
*''Super PakPak'' (NES and Famicom)<br />
<br />
Tech demos:<br />
*''Eighty'' (NES and Famicom)<br />
*''allpads'' (NES and Famicom)<br />
<br />
Hacks:<br />
*''Battle City - 4 Players v1.3 Ti'' (NES and Famicom)<br />
*''Battle City Mario - 4 players v1.0 NesDraug'' (NES and Famicom)<br />
*''Battletoads - 4 players v2.2 NakeuD2007'' (emulator only)<br />
*''Battletoads & Double Dragon - 4 players v0.9 NakeuD2007'' (emulator only)<br />
*''Super Dodge Ball - 4 Player Hack v1.00 akatranslations'' (Famicom)<br />
<br />
=Incompatible Games=<br />
This section lists games that provide four player game modes without supporting a four player adapter. They are explicitly enumerated here because various lists, including one in Wikipedia, frivolously keep listing (and re-adding after an edit to remove them) these games as supporting a four player adapter.<br />
*''Championship Bowling'': Manual clearly states "Players One and Three use Control Pad 1, and Players Two and Four use Control Pad 2".<br />
*''Jeopardy!'' series: Players 1 and 3 share controller 1.<br />
<br />
= References =<br />
<References/><br />
* [//forums.nesdev.org/viewtopic.php?p=237997#p237997 Forum post]: Analysis of Wit's controller reading, and speculation about the Hori 4 Players adapter.<br />
* [http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=65237 NintendoAge forum thread]: Photos of Four Score PCB and hardware discussion.<br />
* [https://www.famicomworld.com/forum/index.php?topic=12543.15 Famicom World forum post]: List of Famicom games and their behaviour with Hori 4 Players adapter.<br />
* [//forums.nesdev.org/viewtopic.php?p=238168#p238168 Forum post]: Discussion of Hori 4 Players support in ''Micro Mages''.<br />
[[Category:Controllers]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:NES-Satellite.jpg&diff=21538File:NES-Satellite.jpg2024-01-17T17:34:51Z<p>Fiskbit: The NES Satellite, a wireless four player adapter.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The NES Satellite, a wireless four player adapter.<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Zapper&diff=21537Zapper2024-01-17T17:33:14Z<p>Fiskbit: Adds a gray Zapper image.</p>
<hr />
<div>[[File:Nintendo-Entertainment-System-NES-Zapper-Gray-R.jpg|400px|thumb|right|NES Zapper (gray)]]<br />
The '''Zapper''' is a light gun, often associated with the game ''Duck Hunt''.<br />
It reads light from a CRT SDTV and sends the brightness of the area where it is pointed on the controller port.<br />
<br />
The Zapper can be used in either [[Input_devices|controller port]], though most games will only allow you to use it in controller port #2, leaving port #1 for a standard controller used for navigating through options, moving the view, changing weapons, etc.<br />
<br />
The Famicom Zapper is logically compatible, but can only be plugged into the [[Famicom expansion port pinout|Famicom expansion port]] and so only read from $4017 (i.e. controller port #2). The Vs. System Zapper is not compatible<ref>[//forums.nesdev.org/viewtopic.php?f=3&t=9917 Forum post:] VS zapper info?</ref> (see below).<br />
<br />
=== Output ($4016/$4017 read) ===<br />
7 bit 0<br />
---- ----<br />
xxxT WxxS<br />
| | |<br />
| | +- Serial data (Vs.)<br />
| +---- Light sensed at the current scanline (0: detected; 1: not detected) (NES/FC)<br />
+------ Trigger (0: released or fully pulled; 1: half-pulled) (NES/FC)<br />
<br />
There are three hardware variants:<br />
;NES: Light sense and trigger are output on bit 3 and 4 of $4016 or $4017, depending on the port.<br />
;Famicom: Light sense and trigger are output on bit 3 and 4 of $4017, as if the Zapper were plugged into port 2 of the NES. The pins for bits 3 and 4 in an AV Famicom's controller ports are normally not connected, but there is a published hardware modification to use an NES Zapper.<br />
;Vs. System: This Zapper communicates with the same protocol as the [[standard controller]], returning an 8-bit report after being strobed:<br />
:: 0, 0, 0, 0, 1, 0, Light sense (inverted), Trigger<br />
:The "light sense" status corresponds to Left and the "trigger" to Right, and Up is always pressed.<br />
:Unlike the NES/Famicom Zapper, the Vs. Zapper's "light sense" is 1 when detecting and 0 when not detecting.<br />
<br />
Tests in the Zap Ruder test ROM show that the photodiode stays on for about 26 scanlines with pure white, 24 scanlines with light gray, or 19 lines with dark gray.<br />
For an emulator developer, one useful model of the light sensor's behavior is that luminance is collected as voltage into a capacitor, whose voltage drains out exponentially over the course of several scanlines, and the light bit is active while the voltage is above a threshold.<br />
<br />
The official Zapper's trigger returns 0 while the trigger is fully open, 1 while it is halfway in, and 0 again after it has been pulled all the way to where it goes clunk.<br />
The large capacitor (10µF) inside the Zapper when combined with the 10kΩ pullup inside the console means that it will take approximately 100ms to change to "released" after the trigger has been half-pulled.<br />
<br />
Some clone zappers, like the Tomee Zapp Gun implement a simpler switch that returns 1 while the trigger is not pulled, and 0 when it is pulled. This works with most existing zapper games which usually fire on a transition from 1 to 0.<br />
<br />
=== Light Sensor ===<br />
<br />
The light sensor in the NES Zapper has a filter tuned approimately to the CRT scanline frequency (~15 kHz). This helps filter out more slowly changing light signals (e.g. light bulbs), but unfortunately will strongly attenuate the light signal from many modern televisions (e.g. LCD based). Some clone zappers (e.g. Tomee Zapp Gun, or Simba's Jr) have a much weaker filter that responds more readily to these slower changing light sources.<br />
<br />
Light gun games also tend to expect no effective delay from the CRT, allowing the sensor to give a reading immediately as the picture is being drawn on the TV screen. This is also a problem for most modern televisions, which tend to have inherent delay (display lag).<br />
<br />
A combination of clone hardware with a weaker filter, and a software patch to compensate for the display lag delay can be effective for getting some zapper games to work with a modern television.<ref>[//forums.nesdev.org/viewtopic.php?p=225882#p225882 NES zapper + LCD]: forum thread discussing the "NES LCD Mod" project.</ref><br />
<br />
=== Sequence of operations ===<br />
The common way to implement Zapper support in a game is as follows:<br />
# Each frame, check if the player has pulled the trigger. Keep running the game loop and remain in this step until the trigger is pulled.<br />
# During vertical blanking, verify that the light gun is ''not'' detecting light, to ensure that the player is actually pointing the gun at the screen. If bit 3 is false during vblank, a [[standard controller]] is probably plugged in. Do this near the end of your vertical blank code to let the light "drain out" if the gun happens to be pointed near the bottom of the screen. If you are using sprite 0 hit, a good time to read it is right after the sprite 0 hit flag turns off.<br />
# Optional: Turn the entire screen white or display white boxes on all targets, and use timed code or a scanline IRQ handler to wait for the Zapper to start detecting light in order to see how far down the screen the Zapper is pointed. This can narrow the set of targets that must be checked in the next step.<br />
# For each target the player may hit, display a black screen with a single white ($20) or light colored ($31-$3C) box at the target's location. Wait the entire frame to check if the light sense bit goes low. The sensor may turn on and off in 10 to 25 scanlines, so continue to check throughout a whole frame. If any of the targets is hit, register a 'hit' within the game; if not, move on to the next target or, if there are no additional targets, register a 'miss'.<br />
# Restore the screen to its original state.<br />
<br />
== Trivia ==<br />
In ''Wild Gunman'' (mode: GAME A: 1 OUTLAW), game's engine does not check what light gun is pointing at but just the time when trigger is pressed. As a result, this title is good choice nowadays for (partial) test of Zapper, where analog CRT TVs are quite rare to find.<br />
<br />
== External Links ==<br />
<br />
*[//forums.nesdev.org/viewtopic.php?f=9&t=13021 Forum post:] Zapper test ROMs<br />
*[//forums.nesdev.org/viewtopic.php?t=8108 Forum post:] Zap Ruder: The Zapper test ROM project<br />
*[//forums.nesdev.org/viewtopic.php?f=3&t=11169 Forum post:] Zapruder calibration<br />
*[//forums.nesdev.org/viewtopic.php?t=10138 Forum post:] Detecting screen (X,Y) location for the NES Zapper<br />
<br />
== References ==<br />
<references/><br />
<br />
[[Category:Controllers]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Nintendo-Entertainment-System-NES-Zapper-Gray-R.jpg&diff=21536File:Nintendo-Entertainment-System-NES-Zapper-Gray-R.jpg2024-01-17T17:31:02Z<p>Fiskbit: The NES Zapper (gray version).
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The NES Zapper (gray version).<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Famicom_3D_System&diff=21535Famicom 3D System2024-01-17T17:28:50Z<p>Fiskbit: Adds a caption on the device image.</p>
<hr />
<div>[[File:Famicom-3D-System.jpg|400px|thumb|right|Famicom 3D System]]<br />
The [[Famicom 3D System]] is a Famicom expansion port device that uses active LCD shutter glasses to provide 3D visuals. The headset (HVC-031) plugs into a control box (HVC-032) using a 3.5mm connector. The control box has two such ports, allowing up to two headsets, and passes through a Famicom expansion port so other controllers can be used. Compatible games manually control which eye sees which frame, alternating to give each eye a unique perspective that creates a 30 Hz stereoscopic image. While these glasses do not require a CRT TV to correctly function, modern TVs without very low latency and some kind of impulse display, such as black frame insertion, may not be compatible.<br />
<br />
The 3D System is supported by the following Famicom games:<br />
* ''Attack Animal Gakuen'' (1987)<br />
* ''Cosmic Epsilon'' (1989)<br />
* ''Falsion'' (1987)<br />
* ''Famicom Grand Prix II: 3D Hot Rally'' (1988)<br />
* ''Fuuun Shourin Ken: Ankoku no Maou'' (1988)<br />
* ''Highway Star'' (1987)<br />
* ''JJ: Tobidase Daisakusen Part II'' (1987)<br />
* ''Tobidase Daisakusen'' (1987)<br />
<br />
In these games, the 3D mode can be toggled with the select button except in ''Fuuun Shourin Ken: Ankoku no Maou'', where the mode is enabled by holding A while pressing start on the title screen.<br />
<br />
Note that the 3D System was only released in Japan. Versions of these games released internationally (''3-D WorldRunner'' and ''Rad Racer'') instead achieve 3D with an anaglyph mode using passive red and cyan glasses.<br />
<br />
=== Output ($4016 write) ===<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxFx<br />
|<br />
+--- 0: Next field of video is for left eye (left eye lens is transparent; right eye lens is opaque)<br />
1: Next field of video is for right eye<br />
<br />
Because the Famicom only generated images at 60Hz, each resultant image will flicker at 30Hz.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Famicom_3D_System&diff=21534Famicom 3D System2024-01-17T17:01:59Z<p>Fiskbit: Rewrites the page opening with more meaningful information than a Wikipedia quote. Adds a games list (thank you to Retronika). Adds a device image.</p>
<hr />
<div>[[File:Famicom-3D-System.jpg|400px|right]]<br />
The [[Famicom 3D System]] is a Famicom expansion port device that uses active LCD shutter glasses to provide 3D visuals. The headset (HVC-031) plugs into a control box (HVC-032) using a 3.5mm connector. The control box has two such ports, allowing up to two headsets, and passes through a Famicom expansion port so other controllers can be used. Compatible games manually control which eye sees which frame, alternating to give each eye a unique perspective that creates a 30 Hz stereoscopic image. While these glasses do not require a CRT TV to correctly function, modern TVs without very low latency and some kind of impulse display, such as black frame insertion, may not be compatible.<br />
<br />
The 3D System is supported by the following Famicom games:<br />
* ''Attack Animal Gakuen'' (1987)<br />
* ''Cosmic Epsilon'' (1989)<br />
* ''Falsion'' (1987)<br />
* ''Famicom Grand Prix II: 3D Hot Rally'' (1988)<br />
* ''Fuuun Shourin Ken: Ankoku no Maou'' (1988)<br />
* ''Highway Star'' (1987)<br />
* ''JJ: Tobidase Daisakusen Part II'' (1987)<br />
* ''Tobidase Daisakusen'' (1987)<br />
<br />
In these games, the 3D mode can be toggled with the select button except in ''Fuuun Shourin Ken: Ankoku no Maou'', where the mode is enabled by holding A while pressing start on the title screen.<br />
<br />
Note that the 3D System was only released in Japan. Versions of these games released internationally (''3-D WorldRunner'' and ''Rad Racer'') instead achieve 3D with an anaglyph mode using passive red and cyan glasses.<br />
<br />
=== Output ($4016 write) ===<br />
<br />
7 bit 0<br />
---- ----<br />
xxxx xxFx<br />
|<br />
+--- 0: Next field of video is for left eye (left eye lens is transparent; right eye lens is opaque)<br />
1: Next field of video is for right eye<br />
<br />
Because the Famicom only generated images at 60Hz, each resultant image will flicker at 30Hz.</div>Fiskbithttps://www.nesdev.org/w/index.php?title=File:Famicom-3D-System.jpg&diff=21533File:Famicom-3D-System.jpg2024-01-17T16:56:03Z<p>Fiskbit: The Famicom 3D System, a 3D shutter-glass expansion port device.
Image by Evan Amos</p>
<hr />
<div>== Summary ==<br />
The Famicom 3D System, a 3D shutter-glass expansion port device.<br />
<br />
Image by Evan Amos<br />
== Licensing ==<br />
{{cc0-1.0}}</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Turbo_File&diff=21530Turbo File2024-01-17T15:49:48Z<p>Fiskbit: Reverted edits by Retronika (talk) to last revision by Qalle</p>
<hr />
<div>The Turbo File (for [[Famicom|Family Computer]]) is a Famicom expansion port peripheral developed by ASCII Corporation, and is used to store save data for certain games. Variants of the device were also produced for the Game Boy (Turbo File GB), Game Boy Advance (Turbo File Advance), and Super Famicom (Turbo File Twin).<br />
<br />
The device exists in two iterations; the original model (AS-TFO2) containing 8K of battery-backed SRAM and a write protect switch, and the Turbo File II (TFII) containing 32K of battery-backed SRAM (which is divided into four 8K banks that can be switched using a four-way SELECT switch, thus allowing for four game saves) as well as the write protect switch from the original. Both devices also have an LED that illuminates when connected to a Famicom that is powered on.<br />
<br />
Games that support the Turbo File include:<br />
*''Best Keiba - Derby Stallion'' (1991)<br />
*''Best Play Pro Yakyuu II'' (1990)<br />
*''Best Play Pro Yakyuu Special'' (1992)<br />
*''Castle Excellent'' (1986)<br />
*''Derby Stallion - Zenkoku Ban'' (1992)<br />
*''Downtown - Nekketsu Monogatari'' (1989)<br />
*''Dungeon Kid'' (1990)<br />
*''Famicom Shougi - Ryuuousen'' (1991)<br />
*''Fleet Commander'' (1988)<br />
*''Haja no Fuuin'' (1987)<br />
*''Itadaki Street - Watashi no Mise ni Yottette'' (1990)<br />
*''The Money Game 2 - Kabutochou no Kiseki'' (1989)<br />
*''Ninjara Hoi!'' (1990)<br />
*''Wizardry - Legacy of Llylgamyn'' (1989)<br />
*''Wizardry - Proving Grounds of the Mad Overlord'' (1987)<br />
*''Wizardry - The Knight of Diamonds'' (1991)<br />
These titles all bear a "TF" logo on the cartridge label signifying their compatibility.<br />
<br />
Games that are believed to potentially work with the device (but remain unconfirmed) include:<br />
*''Castlequest'' (1989) (US version of ''Castle Excellent''.)<br />
*''Kunio 8-in-1'' (Pirate multicart that contains ''Downtown - Nekketsu Monogatari'' listed as "HEROS STORY" in the selection menu.)<br />
<br />
== Memory Setup and File Format ==<br />
The first byte of memory (offset 0000h) is unused, potentially out of fear that certain games with controller access might disrupt it, so a dummy byte is used to skip it after resetting the address. All the rest of the space (0001h-1FFFh) is used to store save data, with files being attached directly after each other. Invalid file IDs indicate the start of free memory.<br />
<br />
The majority of Turbo File games utilize this format for save files:<br />
2 ID "AB" (41h,42h)<br />
2 Filesize (16+N+2) (including title and checksum)<br />
16 Title in ASCII (terminated by 00h or 01h)<br />
N Data Portion<br />
2 Checksum (all N bytes in Data Portion added together)<br />
<br />
The exception to this, ''Castle Excellent'', uses a unique file format, shown here:<br />
1 Don't care (should be 00h) ;fixed, at offset 0001h<br />
2 ID AAh,55h ;fixed, at offset 0002h..0003h<br />
508 Data Portion (Data, end code "BEDEUTUN", followed by some unused bytes)<br />
This game also forgoes a filename and utilizes a hardcoded memory offset of 511 bytes (0001h-01FFh).<br />
Due to the hardcoded memory offset, ''Castle Excellent'' will destroy any other file that is located at the same address.<br />
<br />
== Reference ==<br />
* nocash's NES documentation: https://problemkaputt.de/everynes.htm#storageturbofile<br />
<br />
[[Category:File formats]]<br />
[[Category:Hardware]]</div>Fiskbithttps://www.nesdev.org/w/index.php?title=Famicom_3D_glasses&diff=21527Famicom 3D glasses2024-01-17T15:32:03Z<p>Fiskbit: Fiskbit moved page Famicom 3D glasses to Famicom 3D System: Moves page to match the device's name.</p>
<hr />
<div>#REDIRECT [[Famicom 3D System]]</div>Fiskbit