summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes_ctrl/zapper.cpp
diff options
context:
space:
mode:
author 0kmg <9137159+0kmg@users.noreply.github.com>2022-02-09 09:18:19 -0900
committer GitHub <noreply@github.com>2022-02-09 13:18:19 -0500
commit0d8ac5b7608e87160071d41d2b98040f98f11132 (patch)
treef594b52646cae5a2f980f228aeed2996f001ffa2 /src/devices/bus/nes_ctrl/zapper.cpp
parent56db643ab0315a0d6ffbaf708afc1c6f599bdbf2 (diff)
nes.cpp, playch10.cpp, vsnes.cpp: Made zapper less bad. (#9284)
- Limited light detection to scanlines recently drawn by CRT. - Lowered light detection threshold to better reflect how real zapper behaves; color doesn't need to be white. - Bugs fixed: * not detecting hits on certain white objects * misdetecting hits on objects far away from the pointer * not being able to track where zapper is pointed in demo/test software
Diffstat (limited to 'src/devices/bus/nes_ctrl/zapper.cpp')
-rw-r--r--src/devices/bus/nes_ctrl/zapper.cpp51
1 files changed, 33 insertions, 18 deletions
diff --git a/src/devices/bus/nes_ctrl/zapper.cpp b/src/devices/bus/nes_ctrl/zapper.cpp
index e19c63fa2d2..4a1a2dd9408 100644
--- a/src/devices/bus/nes_ctrl/zapper.cpp
+++ b/src/devices/bus/nes_ctrl/zapper.cpp
@@ -21,11 +21,11 @@ DEFINE_DEVICE_TYPE(NES_BANDAIHS, nes_bandaihs_device, "nes_bandaihs", "Bandai Hy
static INPUT_PORTS_START( nes_zapper )
PORT_START("ZAPPER_X")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255)
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0, 255)
PORT_START("ZAPPER_Y")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255)
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0, 239)
PORT_START("ZAPPER_T")
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Lightgun Trigger")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Lightgun Trigger")
INPUT_PORTS_END
@@ -116,25 +116,40 @@ u8 nes_zapper_device::read_bit34()
int x = m_lightx->read();
int y = m_lighty->read();
+ // effective range picked up by photodiode, i.e. gun position +- radius
+ constexpr int xrad = 0;
+ constexpr int yrad = 0;
+ // brightness threshold
+ constexpr int bright = 0x70;
+ // # of CRT scanlines that sustain brightness
+ constexpr int sustain = 20;
+
+ int vpos = m_port->m_screen->vpos();
+ int hpos = m_port->m_screen->hpos();
+
// update the screen if necessary
if (!m_port->m_screen->vblank())
- {
- int vpos = m_port->m_screen->vpos();
- int hpos = m_port->m_screen->hpos();
-
- if (vpos > y || (vpos == y && hpos >= x))
+ if (vpos > y - yrad || (vpos == y - yrad && hpos >= x - xrad))
m_port->m_screen->update_now();
- }
-
- // get the pixel at the gun position
- rgb_t pix = m_port->m_screen->pixel(x, y);
- // check if the cursor is over a bright pixel
- // FIXME: still a gross hack
- if (pix.r() == 0xff && pix.b() == 0xff && pix.g() > 0x90)
- ret &= ~0x08; // sprite hit
- else
- ret |= 0x08; // no sprite hit
+ // default to no light detected
+ ret |= 0x08;
+
+ // check brightness of pixels nearby the gun position
+ for (int i = x - xrad; i <= x + xrad; i++)
+ for (int j = y - yrad; j <= y + yrad; j++)
+ {
+ rgb_t pix = m_port->m_screen->pixel(i, j);
+
+ // only detect light if gun position is near, and behind, where the PPU is drawing on the CRT, from NesDev wiki:
+ // "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."
+ if (j <= vpos && j > vpos - sustain && (j != vpos || i <= hpos) && pix.brightness() >= bright)
+ {
+ ret &= ~0x08; // light detected
+ i = x + xrad;
+ break;
+ }
+ }
return ret;
}