diff options
| author | 2022-02-09 09:18:19 -0900 | |
|---|---|---|
| committer | 2022-02-09 13:18:19 -0500 | |
| commit | 0d8ac5b7608e87160071d41d2b98040f98f11132 (patch) | |
| tree | f594b52646cae5a2f980f228aeed2996f001ffa2 /src/devices/bus/nes_ctrl/zapper.cpp | |
| parent | 56db643ab0315a0d6ffbaf708afc1c6f599bdbf2 (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.cpp | 51 |
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; } |
