Zapper: Difference between revisions
From NESdev Wiki
Jump to navigationJump to search
(→Output ($4016/$4017 read): $40 and $80 are misleading because a lot of controller read routines (including the one in the Super NES) are bitwise big-endian, in which case they'd be $02 and $01 respectively. Reworded to be endian-neutral.) |
(→Output ($4016/$4017 read): Centralized description of the three variants) |
||
Line 9: | Line 9: | ||
7 bit 0 | 7 bit 0 | ||
---- ---- | ---- ---- | ||
xxxT | xxxT WxxS | ||
| | | | | | | ||
| +---- Light sense (0: detected; 1: not detected) | | | +- Report (Vs.) | ||
+------ Trigger (0: released; 1: pulled) | | +---- Light sense (0: detected; 1: not detected) (NES/FC) | ||
+------ Trigger (0: released; 1: pulled) (NES/FC) | |||
There are three hardware variants: | |||
;NES: Light sense and trigger are output on bit 3 and 4 of $4016 or $4017, depending on the port. | |||
;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. | |||
;Vs. System: This Zapper communicates with the same protocol as the [[standard controller]], returning an 8-bit report after being strobed: | |||
:: 0, 0, 0, 0, 1, 0, Light sense, Trigger | |||
:The "light sense" status corresponds to Left and the "trigger" to Right, and Up is always pressed. | |||
=== Sequence of operations === | |||
The proper way to implement Zapper support in a game is as follows: | The proper way to implement Zapper support in a game is as follows: | ||
# Each frame, check if the player has pulled the trigger. | # 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. | ||
# 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. | # 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. | ||
# Optional: Turn the entire screen white or display white boxes on all targets, and use timed code 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. | # 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. | ||
# For each target the player may hit, display a black screen with a single white box at the target's location. Wait the entire frame to check if | # 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'. | ||
# Restore the screen to its original state. | # Restore the screen to its original state. | ||
[[Category:Controllers]] | [[Category:Controllers]] |
Revision as of 14:07, 14 March 2013
The Zapper is a light gun, often associated with the game "Duck Hunt". It reads light from a CRT SDTV and sends the brightness of the area where it is pointed on the controller port.
The Zapper can be used in either 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.
The Famicom Zapper is logically compatible, but can only be plugged into the Famicom expansion port and so only read from $4017. The Vs. System Zapper is not compatible - see below.
Output ($4016/$4017 read)
7 bit 0 ---- ---- xxxT WxxS | | | | | +- Report (Vs.) | +---- Light sense (0: detected; 1: not detected) (NES/FC) +------ Trigger (0: released; 1: pulled) (NES/FC)
There are three hardware variants:
- NES
- Light sense and trigger are output on bit 3 and 4 of $4016 or $4017, depending on the port.
- 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.
- Vs. System
- This Zapper communicates with the same protocol as the standard controller, returning an 8-bit report after being strobed:
- 0, 0, 0, 0, 1, 0, Light sense, Trigger
- The "light sense" status corresponds to Left and the "trigger" to Right, and Up is always pressed.
Sequence of operations
The proper way to implement Zapper support in a game is as follows:
- 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.
- 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.
- 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.
- 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'.
- Restore the screen to its original state.