diff --git a/src/emu/screen.c b/src/emu/screen.c index c3bb09e320a..399c376c856 100644 --- a/src/emu/screen.c +++ b/src/emu/screen.c @@ -63,6 +63,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev m_curtexture(0), m_changed(true), m_last_partial_scan(0), + m_partial_scan_hpos(0), m_color(rgb_t(0xff, 0xff, 0xff, 0xff)), m_brightness(0xff), m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds()), @@ -661,21 +662,121 @@ bool screen_device::update_partial(int scanline) void screen_device::update_now() { + // these two checks only apply if we're allowed to skip frames + if (!(m_video_attributes & VIDEO_ALWAYS_UPDATE)) + { + // if skipping this frame, bail + if (machine().video().skip_this_frame()) + { + LOG_PARTIAL_UPDATES(("skipped due to frameskipping\n")); + return; + } + + // skip if this screen is not visible anywhere + if (!machine().render().is_live(*this)) + { + LOG_PARTIAL_UPDATES(("skipped because screen not live\n")); + return; + } + } + int current_vpos = vpos(); int current_hpos = hpos(); + rectangle clip = m_visarea; - // since we can currently update only at the scanline - // level, we are trying to do the right thing by - // updating including the current scanline, only if the - // beam is past the halfway point horizontally. - // If the beam is in the first half of the scanline, - // we only update up to the previous scanline. - // This minimizes the number of pixels that might be drawn - // incorrectly until we support a pixel level granularity - if (current_hpos < (m_width / 2) && current_vpos > 0) - current_vpos = current_vpos - 1; + LOG_PARTIAL_UPDATES(("update_now(): Y=%d, X=%d, last partial %d, partial hpos %d (vis %d %d)\n", current_vpos, current_hpos, m_last_partial_scan, m_partial_scan_hpos, m_visarea.max_x, m_visarea.max_y)); - update_partial(current_vpos); + // start off by doing a partial update up to the line before us, in case that was necessary + if (current_vpos > m_last_partial_scan) + { + // if the line before us was incomplete, we must do it in two pieces + if (m_partial_scan_hpos > 0) + { + INT32 save_scan = m_partial_scan_hpos; + update_partial(current_vpos - 2); + m_partial_scan_hpos = save_scan; + + // now finish the previous partial scanline + int scanline = current_vpos - 1; + if (m_partial_scan_hpos > clip.min_x) + clip.min_x = m_partial_scan_hpos; + if (current_hpos < clip.max_x) + clip.max_x = current_hpos; + if (m_last_partial_scan > clip.min_y) + clip.min_y = m_last_partial_scan; + if (scanline < clip.max_y) + clip.max_y = scanline; + + // if there's something to draw, do it + if ((clip.min_x <= clip.max_x) && (clip.min_y <= clip.max_y)) + { + g_profiler.start(PROFILER_VIDEO); + + screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; + case BITMAP_FORMAT_RGB32: m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + } + + m_partial_updates_this_frame++; + g_profiler.stop(); + m_partial_scan_hpos = 0; + m_last_partial_scan = current_vpos + 1; + } + } + else + { + update_partial(current_vpos - 1); + } + } + + // now draw this partial scanline + clip = m_visarea; + + if (m_partial_scan_hpos > clip.min_x) + clip.min_x = m_partial_scan_hpos; + if (current_hpos < clip.max_x) + clip.max_x = current_hpos; + if (current_vpos > clip.min_y) + clip.min_y = current_vpos; + if (current_vpos < clip.max_y) + clip.max_y = current_vpos; + + // and if there's something to draw, do it + if ((clip.min_x <= clip.max_x) && (clip.min_y <= clip.max_y)) + { + g_profiler.start(PROFILER_VIDEO); + + LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.max_y, clip.min_x, clip.max_x)); + + UINT32 flags = UPDATE_HAS_NOT_CHANGED; + screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; + case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + } + + m_partial_updates_this_frame++; + g_profiler.stop(); + + // if we modified the bitmap, we have to commit + m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; + + // remember where we left off + m_partial_scan_hpos = current_hpos; + m_last_partial_scan = current_vpos; + + // if we completed the line, mark it so + if (current_hpos >= m_visarea.max_x) + { + m_partial_scan_hpos = 0; + m_last_partial_scan = current_vpos + 1; + } + } } @@ -687,6 +788,7 @@ void screen_device::update_now() void screen_device::reset_partial_updates() { m_last_partial_scan = 0; + m_partial_scan_hpos = 0; m_partial_updates_this_frame = 0; m_scanline0_timer->adjust(time_until_pos(0)); } diff --git a/src/emu/screen.h b/src/emu/screen.h index f3aab539cce..095142cf7c7 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -285,6 +285,7 @@ private: UINT8 m_curtexture; // current texture index bool m_changed; // has this bitmap changed? INT32 m_last_partial_scan; // scanline of last partial update + INT32 m_partial_scan_hpos; // horizontal pixel last rendered on this partial scanline bitmap_argb32 m_screen_overlay_bitmap; // screen overlay bitmap UINT32 m_unique_id; // unique id for this screen_device rgb_t m_color; // render color diff --git a/src/mame/drivers/apple2.c b/src/mame/drivers/apple2.c index 8cf74588ffc..9ce873d5048 100644 --- a/src/mame/drivers/apple2.c +++ b/src/mame/drivers/apple2.c @@ -324,9 +324,6 @@ TIMER_DEVICE_CALLBACK_MEMBER(napple2_state::apple2_interrupt) { int scanline = param; - if((scanline % 8) == 0) - machine().first_screen()->update_partial(machine().first_screen()->vpos()); - // update the video system's shadow copy of the system config at the end of the frame if (scanline == 192) { @@ -450,31 +447,39 @@ void napple2_state::do_io(address_space &space, int offset) break; case 0x50: // graphics mode + machine().first_screen()->update_now(); m_video->m_graphics = true; break; case 0x51: // text mode + machine().first_screen()->update_now(); m_video->m_graphics = false; break; case 0x52: // no mix + machine().first_screen()->update_now(); m_video->m_mix = false; break; case 0x53: // mixed mode + machine().first_screen()->update_now(); m_video->m_mix = true; break; case 0x54: // set page 1 + machine().first_screen()->update_now(); m_page2 = false; m_video->m_page2 = false; break; case 0x55: // set page 2 + machine().first_screen()->update_now(); m_page2 = true; m_video->m_page2 = true; break; case 0x56: // select lo-res + machine().first_screen()->update_now(); m_video->m_hires = false; break; case 0x57: // select hi-res + machine().first_screen()->update_now(); m_video->m_hires = true; break; case 0x58: // AN0 off diff --git a/src/mame/drivers/apple2e.c b/src/mame/drivers/apple2e.c index e5eb2193aa8..692a22a9e0b 100644 --- a/src/mame/drivers/apple2e.c +++ b/src/mame/drivers/apple2e.c @@ -779,11 +779,6 @@ TIMER_DEVICE_CALLBACK_MEMBER(apple2e_state::apple2_interrupt) { int scanline = param; - if((scanline % 8) == 0) - { - machine().first_screen()->update_partial(machine().first_screen()->vpos()); - } - if (m_isiic) { update_iic_mouse(); @@ -1101,10 +1096,12 @@ void apple2e_state::do_io(address_space &space, int offset, bool is_iic) switch (offset) { case 0x5e: // SETDHIRES + machine().first_screen()->update_now(); m_video->m_dhires = true; break; case 0x5f: // CLRDHIRES + machine().first_screen()->update_now(); m_video->m_dhires = false; break; } @@ -1155,35 +1152,47 @@ void apple2e_state::do_io(address_space &space, int offset, bool is_iic) break; case 0x50: // graphics mode - m_video->m_graphics = true; break; + machine().first_screen()->update_now(); + m_video->m_graphics = true; + break; case 0x51: // text mode - m_video->m_graphics = false; break; + machine().first_screen()->update_now(); + m_video->m_graphics = false; + break; case 0x52: // no mix - m_video->m_mix = false; break; + machine().first_screen()->update_now(); + m_video->m_mix = false; + break; case 0x53: // mixed mode - m_video->m_mix = true; break; + machine().first_screen()->update_now(); + m_video->m_mix = true; + break; case 0x54: // set page 1 + machine().first_screen()->update_now(); m_page2 = false; m_video->m_page2 = false; auxbank_update(); break; case 0x55: // set page 2 + machine().first_screen()->update_now(); m_page2 = true; m_video->m_page2 = true; auxbank_update(); break; case 0x56: // select lo-res + machine().first_screen()->update_now(); m_video->m_hires = false; auxbank_update(); break; case 0x57: // select hi-res + machine().first_screen()->update_now(); m_video->m_hires = true; auxbank_update(); break; diff --git a/src/mame/video/apple2.c b/src/mame/video/apple2.c index 195fed4ce8f..56419e0f46a 100644 --- a/src/mame/video/apple2.c +++ b/src/mame/video/apple2.c @@ -1236,6 +1236,7 @@ void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, co UINT32 w; UINT16 *artifact_map_ptr; int mon_type = m_sysconfig & 0x03; + int begincol = 0, endcol = 40; /* sanity checks */ if (beginrow < cliprect.min_y) @@ -1245,6 +1246,18 @@ void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, co if (endrow < beginrow) return; + // we generate 2 pixels per "column" so adjust + if (begincol < (cliprect.min_x/14)) + begincol = (cliprect.min_x/14); + if (endcol > (cliprect.max_x/14)) + endcol = (cliprect.max_x/14); + if (cliprect.max_x > 39*14) + endcol = 40; + if (endcol < begincol) + return; + + //printf("HGR draw: page %c, rows %d-%d cols %d-%d\n", m_page2 ? '2' : '1', beginrow, endrow, begincol, endcol); + vram = &m_ram_ptr[(m_page2 ? 0x4000 : 0x2000)]; vram_row[0] = 0; @@ -1252,7 +1265,7 @@ void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, co for (row = beginrow; row <= endrow; row++) { - for (col = 0; col < 40; col++) + for (col = begincol; col < endcol; col++) { offset = ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col)) | ((row & 7) << 10); vram_row[1+col] = vram[offset]; @@ -1266,18 +1279,20 @@ void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, co | (((UINT32) vram_row[col+1] & 0x7f) << 7) | (((UINT32) vram_row[col+2] & 0x7f) << 14); + + // verified on h/w: setting dhires w/o 80col emulates a rev. 0 Apple ][ with no orange/blue + if (m_dhires) + { + artifact_map_ptr = m_hires_artifact_map; + } + else + { + artifact_map_ptr = &m_hires_artifact_map[((vram_row[col + 1] & 0x80) >> 7) * 16]; + } + switch (mon_type) { case 0: - // verified on h/w: setting dhires w/o 80col emulates a rev. 0 Apple ][ with no orange/blue - if (m_dhires) - { - artifact_map_ptr = m_hires_artifact_map; - } - else - { - artifact_map_ptr = &m_hires_artifact_map[((vram_row[col + 1] & 0x80) >> 7) * 16]; - } for (b = 0; b < 7; b++) { v = artifact_map_ptr[((w >> (b + 7-1)) & 0x07) | (((b ^ col) & 0x01) << 3)]; @@ -1302,7 +1317,7 @@ void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, co for (b = 0; b < 7; b++) { v = (w & 1); - w >>= 1; + w >>= 1; *(p++) = v ? GREEN : BLACK; *(p++) = v ? GREEN : BLACK; }