diff --git a/hash/nes.xml b/hash/nes.xml
index ec30182f69b..aa3da586022 100644
--- a/hash/nes.xml
+++ b/hash/nes.xml
@@ -27705,7 +27705,6 @@ license:CC0
-
Operation Wolf (Jpn)
1989
@@ -27727,7 +27726,6 @@ license:CC0
-
Operation Wolf - Take no Prisoners (USA, Rev. 0A)
1989
@@ -27748,7 +27746,6 @@ license:CC0
-
Operation Wolf - Take no Prisoners (Euro)
1992
@@ -45595,6 +45592,7 @@ Also notice that VRAM, WRAM & mirror are probably incorrect for some of these se
+
@@ -48167,6 +48165,7 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
+
@@ -54690,6 +54689,7 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
+
@@ -55269,7 +55269,6 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
-
2 in 1 Uzi Lightgun
199?
@@ -55452,7 +55451,7 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
-
+
3 in 1 Supergun (Tw)
1993
Micro Genius
@@ -55460,6 +55459,7 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
+
@@ -70041,6 +70041,7 @@ Also notice that VRAM & WRAM are probably incorrect for some of these sets, at t
+
@@ -70407,6 +70408,7 @@ Also notice that VRAM & WRAM are probably incorrect for some of these sets, at t
+
diff --git a/src/devices/bus/nes_ctrl/zapper.cpp b/src/devices/bus/nes_ctrl/zapper.cpp
index 4a1a2dd9408..e655ec233ff 100644
--- a/src/devices/bus/nes_ctrl/zapper.cpp
+++ b/src/devices/bus/nes_ctrl/zapper.cpp
@@ -116,40 +116,42 @@ 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;
+ // radius of circle picked up by the gun's photodiode
+ constexpr int radius = 5;
// brightness threshold
- constexpr int bright = 0x70;
+ constexpr int bright = 0xc0;
// # of CRT scanlines that sustain brightness
- constexpr int sustain = 20;
+ constexpr int sustain = 22;
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())
- if (vpos > y - yrad || (vpos == y - yrad && hpos >= x - xrad))
+ if (vpos > y - radius || (vpos == y - radius && hpos >= x - radius))
m_port->m_screen->update_now();
- // default to no light detected
- ret |= 0x08;
+ int sum = 0;
+ int scanned = 0;
- // 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)
+ // sum brightness of pixels nearby the gun position
+ for (int i = x - radius; i <= x + radius; i++)
+ for (int j = y - radius; j <= y + radius; j++)
+ // look at pixels within circular sensor
+ if ((x - i) * (x - i) + (y - j) * (y - j) <= radius * radius)
{
- ret &= ~0x08; // light detected
- i = x + xrad;
- break;
+ 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))
+ sum += pix.r() + pix.g() + pix.b();
+ scanned++;
}
- }
+
+ // light not detected if average brightness is below threshold (default bit 3 is 0: light detected)
+ if (sum < bright * scanned)
+ ret |= 0x08;
return ret;
}
diff --git a/src/mame/machine/playch10.cpp b/src/mame/machine/playch10.cpp
index ff3215ab4a5..7ff2c77096e 100644
--- a/src/mame/machine/playch10.cpp
+++ b/src/mame/machine/playch10.cpp
@@ -224,40 +224,42 @@ uint8_t playch10_state::pc10_in1_r()
int x = ioport("GUNX")->read();
int y = ioport("GUNY")->read();
- // effective range picked up by photodiode, i.e. gun position +- radius
- constexpr int xrad = 0;
- constexpr int yrad = 0;
+ // radius of circle picked up by gun's photodiode
+ constexpr int radius = 5;
// brightness threshold
- constexpr int bright = 0x70;
+ constexpr int bright = 0xc0;
// # of CRT scanlines that sustain brightness
- constexpr int sustain = 20;
+ constexpr int sustain = 22;
int vpos = m_ppu->screen().vpos();
int hpos = m_ppu->screen().hpos();
// update the screen if necessary
if (!m_ppu->screen().vblank())
- if (vpos > y - yrad || (vpos == y - yrad && hpos >= x - xrad))
+ if (vpos > y - radius || (vpos == y - radius && hpos >= x - radius))
m_ppu->screen().update_now();
- // default to no light detected
- ret |= 0x08;
+ int sum = 0;
+ int scanned = 0;
- // 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_ppu->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)
+ // sum brightness of pixels nearby the gun position
+ for (int i = x - radius; i <= x + radius; i++)
+ for (int j = y - radius; j <= y + radius; j++)
+ // look at pixels within circular sensor
+ if ((x - i) * (x - i) + (y - j) * (y - j) <= radius * radius)
{
- ret &= ~0x08; // light detected
- i = x + xrad;
- break;
+ rgb_t pix = m_ppu->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))
+ sum += pix.r() + pix.g() + pix.b();
+ scanned++;
}
- }
+
+ // light not detected if average brightness is below threshold (default bit 3 is 0: light detected)
+ if (sum < bright * scanned)
+ ret |= 0x08;
// now, add the trigger if not masked
if (!m_cntrl_mask)
diff --git a/src/mame/machine/vsnes.cpp b/src/mame/machine/vsnes.cpp
index 855dc5d9b27..45f7522dc88 100644
--- a/src/mame/machine/vsnes.cpp
+++ b/src/mame/machine/vsnes.cpp
@@ -280,37 +280,42 @@ void vsnes_state::gun_in0_w(uint8_t data)
int x = ioport("GUNX")->read();
int y = ioport("GUNY")->read();
- // effective range picked up by photodiode, i.e. gun position +- radius
- constexpr int xrad = 0;
- constexpr int yrad = 0;
+ // radius of circle picked up by the gun's photodiode
+ constexpr int radius = 5;
// brightness threshold
- constexpr int bright = 0x70;
+ constexpr int bright = 0xc0;
// # of CRT scanlines that sustain brightness
- constexpr int sustain = 20;
+ constexpr int sustain = 22;
int vpos = m_ppu1->screen().vpos();
int hpos = m_ppu1->screen().hpos();
// update the screen if necessary
if (!m_ppu1->screen().vblank())
- if (vpos > y - yrad || (vpos == y - yrad && hpos >= x - xrad))
+ if (vpos > y - radius || (vpos == y - radius && hpos >= x - radius))
m_ppu1->screen().update_now();
- // 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_ppu1->screen().pixel(i, j);
+ int sum = 0;
+ int scanned = 0;
- // 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)
+ // sum brightness of pixels nearby the gun position
+ for (int i = x - radius; i <= x + radius; i++)
+ for (int j = y - radius; j <= y + radius; j++)
+ // look at pixels within circular sensor
+ if ((x - i) * (x - i) + (y - j) * (y - j) <= radius * radius)
{
- m_input_latch[0] |= 0x40;
- i = x + xrad;
- break;
+ rgb_t pix = m_ppu1->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))
+ sum += pix.r() + pix.g() + pix.b();
+ scanned++;
}
- }
+
+ // light detected if average brightness is above threshold
+ if (sum >= bright * scanned)
+ m_input_latch[0] |= 0x40;
}
m_input_strobe[0] = data;