summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/screen.cpp')
-rw-r--r--src/emu/screen.cpp243
1 files changed, 115 insertions, 128 deletions
diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp
index 5a9c055bbbb..cf311fb21eb 100644
--- a/src/emu/screen.cpp
+++ b/src/emu/screen.cpp
@@ -12,6 +12,8 @@
#include "screen.h"
#include "emuopts.h"
+#include "fileio.h"
+#include "main.h"
#include "render.h"
#include "rendutil.h"
@@ -554,7 +556,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(-1)
+ , m_partial_scan_hpos(0)
, m_color(rgb_t(0xff, 0xff, 0xff, 0xff))
, m_brightness(0xff)
, m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds())
@@ -683,9 +685,9 @@ void screen_device::device_validity_check(validity_checker &valid) const
osd_printf_error("Non-raster display cannot have a variable width\n");
}
- // check for zero frame rate
- if (m_refresh == 0)
- osd_printf_error("Invalid (zero) refresh rate\n");
+ // check for invalid frame rate
+ if (m_refresh == 0 || m_refresh > ATTOSECONDS_PER_SECOND)
+ osd_printf_error("Invalid (under 1Hz) refresh rate\n");
texture_format texformat = !m_screen_update_ind16.isnull() ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32;
if (m_palette.finder_tag() != finder_base::DUMMY_TAG)
@@ -770,8 +772,6 @@ void screen_device::device_resolve_objects()
// bind our handlers
m_screen_update_ind16.resolve();
m_screen_update_rgb32.resolve();
- m_screen_vblank.resolve_safe();
- m_scanline_cb.resolve();
// assign our format to the palette before it starts
if (m_palette)
@@ -834,15 +834,15 @@ void screen_device::device_start()
m_container->set_user_settings(settings);
// allocate the VBLANK timers
- m_vblank_begin_timer = timer_alloc(TID_VBLANK_START);
- m_vblank_end_timer = timer_alloc(TID_VBLANK_END);
+ m_vblank_begin_timer = timer_alloc(FUNC(screen_device::vblank_begin), this);
+ m_vblank_end_timer = timer_alloc(FUNC(screen_device::vblank_end), this);
// allocate a timer to reset partial updates
- m_scanline0_timer = timer_alloc(TID_SCANLINE0);
+ m_scanline0_timer = timer_alloc(FUNC(screen_device::first_scanline_tick), this);
// allocate a timer to generate per-scanline updates
- if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb)
- m_scanline_timer = timer_alloc(TID_SCANLINE);
+ if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset())
+ m_scanline_timer = timer_alloc(FUNC(screen_device::scanline_tick), this);
// configure the screen with the default parameters
configure(m_width, m_height, m_visarea, m_refresh);
@@ -852,7 +852,7 @@ void screen_device::device_start()
m_vblank_end_time = attotime(0, m_vblank_period);
// start the timer to generate per-scanline updates
- if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb)
+ if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset())
m_scanline_timer->adjust(time_until_pos(0));
// create burn-in bitmap
@@ -887,7 +887,7 @@ void screen_device::device_start()
save_item(NAME(m_vblank_end_time));
save_item(NAME(m_frame_number));
if (m_oldstyle_vblank_supplied)
- logerror("%s: Deprecated legacy Old Style screen configured (MCFG_SCREEN_VBLANK_TIME), please use MCFG_SCREEN_RAW_PARAMS instead.\n",this->tag());
+ logerror("%s: Deprecated legacy Old Style screen configured (set_vblank_time), please use set_raw instead.\n",this->tag());
m_is_primary_screen = (this == screen_device_enumerator(machine().root_device()).first());
}
@@ -930,54 +930,39 @@ void screen_device::device_post_load()
//-------------------------------------------------
-// device_timer - called whenever a device timer
-// fires
+// timer events
//-------------------------------------------------
-void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(screen_device::first_scanline_tick)
{
- switch (id)
+ // first scanline
+ reset_partial_updates();
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- // signal VBLANK start
- case TID_VBLANK_START:
- vblank_begin();
- break;
-
- // signal VBLANK end
- case TID_VBLANK_END:
- vblank_end();
- break;
-
- // first scanline
- case TID_SCANLINE0:
- reset_partial_updates();
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
- {
- pre_update_scanline(0);
- }
- break;
+ pre_update_scanline(0);
+ }
+}
- // subsequent scanlines when scanline updates are enabled
- case TID_SCANLINE:
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
- {
- pre_update_scanline(param);
- }
- if (m_video_attributes & VIDEO_UPDATE_SCANLINE)
- {
- // force a partial update to the current scanline
- update_partial(param);
- }
- if (m_scanline_cb)
- m_scanline_cb(param);
-
- // compute the next visible scanline
- param++;
- if (param > m_visarea.bottom())
- param = m_visarea.top();
- m_scanline_timer->adjust(time_until_pos(param), param);
- break;
+TIMER_CALLBACK_MEMBER(screen_device::scanline_tick)
+{
+ // subsequent scanlines when scanline updates are enabled
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
+ {
+ pre_update_scanline(param);
+ }
+ if (m_video_attributes & VIDEO_UPDATE_SCANLINE)
+ {
+ // force a partial update to the current scanline
+ update_partial(param);
}
+ if (!m_scanline_cb.isunset())
+ m_scanline_cb(param);
+
+ // compute the next visible scanline
+ param++;
+ if (param > m_visarea.bottom())
+ param = m_visarea.top();
+ m_scanline_timer->adjust(time_until_pos(param), param);
}
@@ -1026,7 +1011,7 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
// call the VBLANK start timer now; otherwise, adjust it for the future
attoseconds_t delta = (machine().time() - m_vblank_start_time).as_attoseconds();
if (delta >= m_frame_period)
- vblank_begin();
+ vblank_begin(0);
else
m_vblank_begin_timer->adjust(time_until_vblank_start());
@@ -1064,7 +1049,7 @@ void screen_device::reset_origin(int beamy, int beamx)
// if we are resetting relative to (visarea.bottom() + 1, 0) == VBLANK start,
// call the VBLANK start timer now; otherwise, adjust it for the future
if (beamy == ((m_visarea.bottom() + 1) % m_height) && beamx == 0)
- vblank_begin();
+ vblank_begin(0);
else
m_vblank_begin_timer->adjust(time_until_vblank_start());
}
@@ -1196,55 +1181,56 @@ bool screen_device::update_partial(int scanline)
// otherwise, render
LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.top(), clip.bottom()));
- g_profiler.start(PROFILER_VIDEO);
u32 flags = 0;
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- rectangle scan_clip(clip);
- for (int y = clip.top(); y <= clip.bottom(); y++)
+ auto profile = g_profiler.start(PROFILER_VIDEO);
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- scan_clip.sety(y, y);
- pre_update_scanline(y);
-
- screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
- switch (curbitmap.format())
+ rectangle scan_clip(clip);
+ for (int y = clip.top(); y <= clip.bottom(); y++)
{
- default:
- case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
- case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
- }
+ scan_clip.sety(y, y);
+ pre_update_scanline(y);
- m_partial_updates_this_frame++;
- }
- }
- else
- {
- if (m_type != SCREEN_TYPE_SVG)
- {
- 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;
+ screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
+ case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
+ }
+
+ m_partial_updates_this_frame++;
}
}
else
{
- flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
+ if (m_type != SCREEN_TYPE_SVG)
+ {
+ 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;
+ }
+ }
+ else
+ {
+ flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
+ }
+ m_partial_updates_this_frame++;
}
- m_partial_updates_this_frame++;
+ // stop profiling
}
- 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_last_partial_scan = scanline + 1;
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
return true;
}
@@ -1298,10 +1284,10 @@ void screen_device::update_now()
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)
+ if (m_partial_scan_hpos > 0)
{
// now finish the previous partial scanline
- clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1),
+ clip.set((std::max)(clip.left(), m_partial_scan_hpos),
clip.right(),
(std::max)(clip.top(), m_last_partial_scan),
(std::min)(clip.bottom(), m_last_partial_scan));
@@ -1309,7 +1295,7 @@ void screen_device::update_now()
// if there's something to draw, do it
if (!clip.empty())
{
- g_profiler.start(PROFILER_VIDEO);
+ auto profile = g_profiler.start(PROFILER_VIDEO);
u32 flags = 0;
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
@@ -1333,14 +1319,13 @@ void screen_device::update_now()
}
}
- g_profiler.stop();
m_partial_updates_this_frame++;
// if we modified the bitmap, we have to commit
m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
}
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
m_last_partial_scan++;
}
if (current_vpos > m_last_partial_scan)
@@ -1350,47 +1335,49 @@ void screen_device::update_now()
}
// now draw this partial scanline
- clip = m_visarea;
-
- clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1),
- (std::min)(clip.right(), current_hpos),
- (std::max)(clip.top(), current_vpos),
- (std::min)(clip.bottom(), current_vpos));
-
- // and if there's something to draw, do it
- if (!clip.empty())
+ if (current_hpos > 0)
{
- g_profiler.start(PROFILER_VIDEO);
+ clip = m_visarea;
- LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
+ clip.set((std::max)(clip.left(), m_partial_scan_hpos),
+ (std::min)(clip.right(), current_hpos - 1),
+ (std::max)(clip.top(), current_vpos),
+ (std::min)(clip.bottom(), current_vpos));
- u32 flags = 0;
- screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
+ // and if there's something to draw, do it
+ if (!clip.empty())
{
- pre_update_scanline(current_vpos);
- switch (curbitmap.format())
+ auto profile = g_profiler.start(PROFILER_VIDEO);
+
+ LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
+
+ u32 flags = 0;
+ screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- default:
- case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
- case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ pre_update_scanline(current_vpos);
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ }
}
- }
- else
- {
- switch (curbitmap.format())
+ else
{
- 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;
+ 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();
+ m_partial_updates_this_frame++;
- // if we modified the bitmap, we have to commit
- m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
+ // if we modified the bitmap, we have to commit
+ m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
+ }
}
// remember where we left off
@@ -1407,7 +1394,7 @@ void screen_device::update_now()
void screen_device::reset_partial_updates()
{
m_last_partial_scan = 0;
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
m_partial_updates_this_frame = 0;
m_scanline0_timer->adjust(time_until_pos(0));
}
@@ -1646,7 +1633,7 @@ void screen_device::register_screen_bitmap(bitmap_t &bitmap)
// signal the VBLANK period has begun
//-------------------------------------------------
-void screen_device::vblank_begin()
+TIMER_CALLBACK_MEMBER(screen_device::vblank_begin)
{
// reset the starting VBLANK time
m_vblank_start_time = machine().time();
@@ -1666,7 +1653,7 @@ void screen_device::vblank_begin()
// if no VBLANK period, call the VBLANK end callback immediately, otherwise reset the timer
if (m_vblank_period == 0)
- vblank_end();
+ vblank_end(0);
else
m_vblank_end_timer->adjust(time_until_vblank_end());
}
@@ -1677,7 +1664,7 @@ void screen_device::vblank_begin()
// signal the VBLANK period has ended
//-------------------------------------------------
-void screen_device::vblank_end()
+TIMER_CALLBACK_MEMBER(screen_device::vblank_end)
{
// call the screen specific callbacks
for (auto &item : m_callback_list)