diff --git a/src/devices/bus/nes_ctrl/zapper.cpp b/src/devices/bus/nes_ctrl/zapper.cpp index 195ed891300..746246a8c76 100644 --- a/src/devices/bus/nes_ctrl/zapper.cpp +++ b/src/devices/bus/nes_ctrl/zapper.cpp @@ -82,9 +82,21 @@ void nes_zapper_device::device_reset() uint8_t nes_zapper_device::read_bit34() { uint8_t ret = m_trigger->read(); + int x = m_lightx->read(); + int y = m_lighty->read(); + + // update the screen if necessary + if (!screen().vblank()) + { + int vpos = screen().vpos(); + int hpos = screen().hpos(); + + if (vpos > y || (vpos == y && hpos >= x)) + screen().update_now(); + } // get the pixel at the gun position - rgb_t pix = screen().pixel(m_lightx->read(), m_lighty->read()); + rgb_t pix = screen().pixel(x, y); // check if the cursor is over a bright pixel // FIXME: still a gross hack diff --git a/src/devices/bus/sms_ctrl/lphaser.cpp b/src/devices/bus/sms_ctrl/lphaser.cpp index a728930f50e..261f6b13504 100644 --- a/src/devices/bus/sms_ctrl/lphaser.cpp +++ b/src/devices/bus/sms_ctrl/lphaser.cpp @@ -231,6 +231,7 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int /* brightness of the lightgray color in the frame drawn by Light Phaser games */ const uint8_t sensor_min_brightness = 0x7f; + screen().update_now(); color = screen().pixel(beam_x, beam_y); /* reference: http://www.w3.org/TR/AERT#color-contrast */ diff --git a/src/devices/video/ppu2c0x.cpp b/src/devices/video/ppu2c0x.cpp index f97c91d381b..c4ac3898b4d 100644 --- a/src/devices/video/ppu2c0x.cpp +++ b/src/devices/video/ppu2c0x.cpp @@ -979,10 +979,13 @@ void ppu2c0x_device::update_scanline() /* Render this scanline if appropriate */ if (m_regs[PPU_CONTROL1] & (PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES)) { - /* If background or sprites are enabled, copy the ppu address latch */ - /* Copy only the scroll x-coarse and the x-overflow bit */ - m_refresh_data &= ~0x041f; - m_refresh_data |= (m_refresh_latch & 0x041f); + if (m_scanline_timer->remaining() == attotime::zero) + { + /* If background or sprites are enabled, copy the ppu address latch */ + /* Copy only the scroll x-coarse and the x-overflow bit */ + m_refresh_data &= ~0x041f; + m_refresh_data |= (m_refresh_latch & 0x041f); + } // logerror("updating refresh_data: %04x (scanline: %d)\n", m_refresh_data, m_scanline); render_scanline(); @@ -1014,23 +1017,26 @@ void ppu2c0x_device::update_scanline() bitmap.pix32(m_scanline, i) = back_pen; } - /* increment the fine y-scroll */ - m_refresh_data += 0x1000; - - /* if it's rolled, increment the coarse y-scroll */ - if (m_refresh_data & 0x8000) + if (m_scanline_timer->remaining() == attotime::zero) { - uint16_t tmp; - tmp = (m_refresh_data & 0x03e0) + 0x20; - m_refresh_data &= 0x7c1f; + /* increment the fine y-scroll */ + m_refresh_data += 0x1000; - /* handle bizarro scrolling rollover at the 30th (not 32nd) vertical tile */ - if (tmp == 0x03c0) - m_refresh_data ^= 0x0800; - else - m_refresh_data |= (tmp & 0x03e0); + /* if it's rolled, increment the coarse y-scroll */ + if (m_refresh_data & 0x8000) + { + uint16_t tmp; + tmp = (m_refresh_data & 0x03e0) + 0x20; + m_refresh_data &= 0x7c1f; -// logerror("updating refresh_data: %04x\n", m_refresh_data); + /* handle bizarro scrolling rollover at the 30th (not 32nd) vertical tile */ + if (tmp == 0x03c0) + m_refresh_data ^= 0x0800; + else + m_refresh_data |= (tmp & 0x03e0); + + //logerror("updating refresh_data: %04x\n", m_refresh_data); + } } } @@ -1331,13 +1337,18 @@ void ppu2c0x_device::spriteram_dma( address_space &space, const uint8_t page ) * *************************************/ -void ppu2c0x_device::render(bitmap_rgb32 &bitmap, int flipx, int flipy, int sx, int sy) +void ppu2c0x_device::render(bitmap_rgb32 &bitmap, int flipx, int flipy, int sx, int sy, const rectangle &cliprect) { - copybitmap(bitmap, *m_bitmap, flipx, flipy, sx, sy, bitmap.cliprect()); + if (m_scanline_timer->remaining() != attotime::zero) + { + // Partial line update, need to render first (especially for light gun emulation). + update_scanline(); + } + copybitmap(bitmap, *m_bitmap, flipx, flipy, sx, sy, cliprect); } uint32_t ppu2c0x_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - render(bitmap, 0, 0, 0, 0); + render(bitmap, 0, 0, 0, 0, cliprect); return 0; } diff --git a/src/devices/video/ppu2c0x.h b/src/devices/video/ppu2c0x.h index 1f0eb086369..78ebef0b2ce 100644 --- a/src/devices/video/ppu2c0x.h +++ b/src/devices/video/ppu2c0x.h @@ -92,7 +92,7 @@ public: void update_scanline(); void spriteram_dma(address_space &space, const uint8_t page); - void render(bitmap_rgb32 &bitmap, int flipx, int flipy, int sx, int sy); + void render(bitmap_rgb32 &bitmap, int flipx, int flipy, int sx, int sy, const rectangle &cliprect); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); int get_current_scanline() { return m_scanline; } diff --git a/src/mame/drivers/nes.cpp b/src/mame/drivers/nes.cpp index fc757d17824..5631a9a21fc 100644 --- a/src/mame/drivers/nes.cpp +++ b/src/mame/drivers/nes.cpp @@ -65,6 +65,7 @@ void nes_state::nes(machine_config &config) m_screen->set_size(32*8, 262); m_screen->set_visarea(0*8, 32*8-1, 0*8, 30*8-1); m_screen->set_screen_update(FUNC(nes_state::screen_update_nes)); + m_screen->screen_vblank().set(FUNC(nes_state::screen_vblank_nes)); PPU_2C02(config, m_ppu); m_ppu->set_cpu_tag(m_maincpu); diff --git a/src/mame/includes/nes.h b/src/mame/includes/nes.h index 17d0e8c6437..21d1f8a7d9e 100644 --- a/src/mame/includes/nes.h +++ b/src/mame/includes/nes.h @@ -93,6 +93,7 @@ public: virtual void video_start() override; virtual void video_reset() override; uint32_t screen_update_nes(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + void screen_vblank_nes(int state); void init_famicom(); diff --git a/src/mame/machine/playch10.cpp b/src/mame/machine/playch10.cpp index 2c2c29a9ec3..80f67f75444 100644 --- a/src/mame/machine/playch10.cpp +++ b/src/mame/machine/playch10.cpp @@ -225,6 +225,16 @@ READ8_MEMBER(playch10_state::pc10_in1_r) /* no sprite hit (yet) */ ret |= 0x08; + // update the screen if necessary + if (!m_ppu->screen().vblank()) + { + int vpos = m_ppu->screen().vpos(); + int hpos = m_ppu->screen().hpos(); + + if (vpos > y || (vpos == y && hpos >= x)) + m_ppu->screen().update_now(); + } + /* get the pixel at the gun position */ rgb_t pix = m_ppu->screen().pixel(x, y); diff --git a/src/mame/machine/vsnes.cpp b/src/mame/machine/vsnes.cpp index f7595acba77..317608c8f55 100644 --- a/src/mame/machine/vsnes.cpp +++ b/src/mame/machine/vsnes.cpp @@ -375,6 +375,16 @@ WRITE8_MEMBER(vsnes_state::gun_in0_w) uint8_t realy = (int)y; + // update the screen if necessary + if (!m_ppu1->screen().vblank()) + { + int vpos = m_ppu1->screen().vpos(); + int hpos = m_ppu1->screen().hpos(); + + if (vpos > realy || (vpos == realy && hpos >= x)) + m_ppu1->screen().update_now(); + } + /* get the pixel at the gun position */ rgb_t col = m_ppu1->screen().pixel(x, realy); uint8_t bright = col.brightness(); diff --git a/src/mame/video/nes.cpp b/src/mame/video/nes.cpp index 3d2874acea6..267c63d7b46 100644 --- a/src/mame/video/nes.cpp +++ b/src/mame/video/nes.cpp @@ -31,27 +31,34 @@ void nes_state::video_start() uint32_t nes_state::screen_update_nes(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { // render the ppu - m_ppu->render(bitmap, 0, 0, 0, 0); - - // if this is a disk system game, check for the flip-disk key - if ((m_cartslot && m_cartslot->exists() && (m_cartslot->get_pcb_id() == STD_DISKSYS)) // first scenario = disksys in m_cartslot (= famicom) - || m_disk) // second scenario = disk via fixed internal disk option (fds & famitwin) - { - if (m_io_disksel) - { - // latch this input so it doesn't go at warp speed - if ((m_io_disksel->read() & 0x01) && (!m_last_frame_flip)) - { - if (m_disk) - m_disk->disk_flip_side(); - else - m_cartslot->disk_flip_side(); - m_last_frame_flip = 1; - } - - if (!(m_io_disksel->read() & 0x01)) - m_last_frame_flip = 0; - } - } + m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); return 0; } + +void nes_state::screen_vblank_nes(int state) +{ + // on rising edge + if (!state) + { + // if this is a disk system game, check for the flip-disk key + if ((m_cartslot && m_cartslot->exists() && (m_cartslot->get_pcb_id() == STD_DISKSYS)) // first scenario = disksys in m_cartslot (= famicom) + || m_disk) // second scenario = disk via fixed internal disk option (fds & famitwin) + { + if (m_io_disksel) + { + // latch this input so it doesn't go at warp speed + if ((m_io_disksel->read() & 0x01) && (!m_last_frame_flip)) + { + if (m_disk) + m_disk->disk_flip_side(); + else + m_cartslot->disk_flip_side(); + m_last_frame_flip = 1; + } + + if (!(m_io_disksel->read() & 0x01)) + m_last_frame_flip = 0; + } + } + } +} diff --git a/src/mame/video/playch10.cpp b/src/mame/video/playch10.cpp index 990820cdfb4..c2e212b45a1 100644 --- a/src/mame/video/playch10.cpp +++ b/src/mame/video/playch10.cpp @@ -111,7 +111,7 @@ uint32_t playch10_state::screen_update_playch10_single(screen_device &screen, bi if (m_pc10_game_mode) /* render the ppu */ - m_ppu->render(bitmap, 0, 0, 0, 0); + m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); else { /* When the bios is accessing vram, the video circuitry can't access it */ @@ -129,7 +129,7 @@ uint32_t playch10_state::screen_update_playch10_top(screen_device &screen, bitma if (!m_pc10_dispmask) /* render the ppu */ - m_ppu->render(bitmap, 0, 0, 0, 0); + m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); else bitmap.fill(0, cliprect);