mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
-screen: Added support for screens that vary horizontal width mid-frame, and hooked it up to the SNES driver. Fixes dkongcu intro and others. [Ryan Holtz]
This commit is contained in:
parent
e0bac48f8f
commit
100767b3df
@ -1865,7 +1865,7 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
|
||||
|
||||
if (m_screen_disabled) /* screen is forced blank */
|
||||
for (int x = 0; x < SNES_SCR_WIDTH * 2; x++)
|
||||
bitmap.pix32(curline, x) = rgb_t::black();
|
||||
bitmap.pix32(0, x) = rgb_t::black();
|
||||
else
|
||||
{
|
||||
/* Update clip window masks if necessary */
|
||||
@ -1947,8 +1947,8 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
|
||||
int g = (((c & 0x3e0) >> 5) * fade) >> 4;
|
||||
int b = (((c & 0x7c00) >> 10) * fade) >> 4;
|
||||
|
||||
bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
bitmap.pix32(0, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
bitmap.pix32(0, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1986,7 +1986,7 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
|
||||
int g = (((c & 0x3e0) >> 5) * fade) >> 4;
|
||||
int b = (((c & 0x7c00) >> 10) * fade) >> 4;
|
||||
|
||||
bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
bitmap.pix32(0, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
prev_colour = tmp_col0;
|
||||
|
||||
/* average the second pixel if required, or draw it directly*/
|
||||
@ -1999,7 +1999,7 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
|
||||
g = (((c & 0x3e0) >> 5) * fade) >> 4;
|
||||
b = (((c & 0x7c00) >> 10) * fade) >> 4;
|
||||
|
||||
bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
bitmap.pix32(0, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
|
||||
prev_colour = tmp_col1;
|
||||
}
|
||||
}
|
||||
|
@ -531,7 +531,12 @@ void screen_device::svg_renderer::rebuild_cache()
|
||||
//-------------------------------------------------
|
||||
|
||||
screen_device::screen_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SCREEN, tag, owner, clock)
|
||||
: screen_device(mconfig, SCREEN, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
screen_device::screen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_type(SCREEN_TYPE_RASTER)
|
||||
, m_orientation(ROT0)
|
||||
, m_phys_aspect(0U, 0U)
|
||||
@ -548,6 +553,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev
|
||||
, m_video_attributes(0)
|
||||
, m_svg_region(*this, DEVICE_SELF)
|
||||
, m_container(nullptr)
|
||||
, m_max_width(100)
|
||||
, m_width(100)
|
||||
, m_height(100)
|
||||
, m_visarea(0, 99, 0, 99)
|
||||
@ -608,6 +614,11 @@ void screen_device::device_validity_check(validity_checker &valid) const
|
||||
if (m_screen_update_ind16.isnull() && m_screen_update_rgb32.isnull())
|
||||
osd_printf_error("Missing SCREEN_UPDATE function\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
osd_printf_error("Non-raster display cannot have a variable width\n");
|
||||
}
|
||||
|
||||
// check for zero frame rate
|
||||
if (m_refresh == 0)
|
||||
@ -735,7 +746,8 @@ void screen_device::device_start()
|
||||
|
||||
// configure bitmap formats and allocate screen bitmaps
|
||||
// svg is RGB32 too, and doesn't have any update method
|
||||
texture_format texformat = !m_screen_update_ind16.isnull() ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32;
|
||||
const bool screen16 = !m_screen_update_ind16.isnull();
|
||||
texture_format texformat = screen16 ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32;
|
||||
|
||||
for (auto & elem : m_bitmap)
|
||||
{
|
||||
@ -750,6 +762,25 @@ void screen_device::device_start()
|
||||
m_texture[1] = machine().render().texture_alloc();
|
||||
m_texture[1]->set_id((u64(m_unique_id) << 57) | 1);
|
||||
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
for (int i = 0; i < m_height; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
if (screen16)
|
||||
{
|
||||
m_scan_bitmaps[j].push_back(new bitmap_ind16(m_width, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scan_bitmaps[j].push_back(new bitmap_rgb32(m_width, 1));
|
||||
}
|
||||
}
|
||||
m_scan_widths.push_back(m_width);
|
||||
}
|
||||
}
|
||||
|
||||
// configure the default cliparea
|
||||
render_container::user_settings settings;
|
||||
m_container->get_user_settings(settings);
|
||||
@ -877,10 +908,18 @@ void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param
|
||||
// first scanline
|
||||
case TID_SCANLINE0:
|
||||
reset_partial_updates();
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
pre_update_scanline(0);
|
||||
}
|
||||
break;
|
||||
|
||||
// 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
|
||||
@ -917,12 +956,20 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
|
||||
assert(frame_period > 0);
|
||||
|
||||
// fill in the new parameters
|
||||
m_max_width = std::max(m_max_width, width);
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_visarea = visarea;
|
||||
|
||||
// reallocate bitmap if necessary
|
||||
realloc_screen_bitmaps();
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
update_scan_bitmap_size(vpos());
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_screen_bitmaps();
|
||||
}
|
||||
|
||||
// compute timing parameters
|
||||
m_frame_period = frame_period;
|
||||
@ -987,6 +1034,29 @@ void screen_device::reset_origin(int beamy, int beamx)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// update_scan_bitmap_size - reallocate the
|
||||
// bitmap for a specific scanline
|
||||
//-------------------------------------------------
|
||||
|
||||
void screen_device::update_scan_bitmap_size(int y)
|
||||
{
|
||||
// determine effective size to allocate
|
||||
s32 effwidth = std::max(m_max_width, m_visarea.right() + 1);
|
||||
|
||||
if (machine().input().code_pressed(KEYCODE_Q))
|
||||
{
|
||||
printf("Updating scan bitmap %d to %d (%d vs. %d)\n", y, effwidth, m_max_width, m_visarea.right() + 1);
|
||||
}
|
||||
|
||||
if (m_scan_widths[y] == effwidth)
|
||||
return;
|
||||
|
||||
m_scan_bitmaps[m_curbitmap][y]->resize(effwidth, 1);
|
||||
m_scan_widths[y] = effwidth;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// realloc_screen_bitmaps - reallocate bitmaps
|
||||
// and textures as necessary
|
||||
@ -999,7 +1069,8 @@ void screen_device::realloc_screen_bitmaps()
|
||||
return;
|
||||
|
||||
// determine effective size to allocate
|
||||
s32 effwidth = std::max(m_width, m_visarea.right() + 1);
|
||||
const bool per_scanline = (m_video_attributes & VIDEO_VARIABLE_WIDTH);
|
||||
s32 effwidth = std::max(per_scanline ? m_max_width : m_width, m_visarea.right() + 1);
|
||||
s32 effheight = std::max(m_height, m_visarea.bottom() + 1);
|
||||
|
||||
// reize all registered screen bitmaps
|
||||
@ -1017,6 +1088,17 @@ void screen_device::realloc_screen_bitmaps()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// pre_update_scanline - check if the bitmap for
|
||||
// a specific scanline needs its size updated
|
||||
//-------------------------------------------------
|
||||
|
||||
void screen_device::pre_update_scanline(int y)
|
||||
{
|
||||
update_scan_bitmap_size(y);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_visible_area - just set the visible area
|
||||
//-------------------------------------------------
|
||||
@ -1066,9 +1148,7 @@ bool screen_device::update_partial(int scanline)
|
||||
|
||||
// set the range of scanlines to render
|
||||
rectangle clip(m_visarea);
|
||||
clip.sety(
|
||||
(std::max)(clip.top(), m_last_partial_scan),
|
||||
(std::min)(clip.bottom(), scanline));
|
||||
clip.sety((std::max)(clip.top(), m_last_partial_scan), (std::min)(clip.bottom(), scanline));
|
||||
|
||||
// skip if entirely outside of visible area
|
||||
if (clip.top() > clip.bottom())
|
||||
@ -1081,23 +1161,45 @@ bool screen_device::update_partial(int scanline)
|
||||
LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.top(), clip.bottom()));
|
||||
g_profiler.start(PROFILER_VIDEO);
|
||||
|
||||
u32 flags;
|
||||
if (m_type != SCREEN_TYPE_SVG)
|
||||
u32 flags = 0;
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
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, curbitmap.as_ind16(), clip); break;
|
||||
case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break;
|
||||
scan_clip.sety(y, y);
|
||||
pre_update_scanline(y);
|
||||
|
||||
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++;
|
||||
g_profiler.stop();
|
||||
|
||||
// if we modified the bitmap, we have to commit
|
||||
@ -1147,11 +1249,10 @@ void screen_device::update_now()
|
||||
if (m_partial_scan_hpos > 0)
|
||||
{
|
||||
// now finish the previous partial scanline
|
||||
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));
|
||||
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));
|
||||
|
||||
// if there's something to draw, do it
|
||||
if (!clip.empty())
|
||||
@ -1159,11 +1260,24 @@ void screen_device::update_now()
|
||||
g_profiler.start(PROFILER_VIDEO);
|
||||
|
||||
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
|
||||
switch (curbitmap.format())
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
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;
|
||||
pre_update_scanline(m_last_partial_scan);
|
||||
switch (curbitmap.format())
|
||||
{
|
||||
default:
|
||||
case BITMAP_FORMAT_IND16: m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][m_last_partial_scan], clip); break;
|
||||
case BITMAP_FORMAT_RGB32: m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][m_last_partial_scan], clip); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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++;
|
||||
@ -1181,11 +1295,10 @@ void screen_device::update_now()
|
||||
// now draw this partial scanline
|
||||
clip = m_visarea;
|
||||
|
||||
clip.set(
|
||||
(std::max)(clip.left(), m_partial_scan_hpos),
|
||||
(std::min)(clip.right(), current_hpos),
|
||||
(std::max)(clip.top(), current_vpos),
|
||||
(std::min)(clip.bottom(), current_vpos));
|
||||
clip.set((std::max)(clip.left(), m_partial_scan_hpos),
|
||||
(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())
|
||||
@ -1194,13 +1307,26 @@ void screen_device::update_now()
|
||||
|
||||
LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
|
||||
|
||||
u32 flags;
|
||||
u32 flags = 0;
|
||||
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
|
||||
switch (curbitmap.format())
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
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;
|
||||
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())
|
||||
{
|
||||
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++;
|
||||
@ -1254,21 +1380,28 @@ u32 screen_device::pixel(s32 x, s32 y)
|
||||
if (x < 0 || y < 0 || x >= srcwidth || y >= srcheight)
|
||||
return 0;
|
||||
|
||||
const bool per_scanline = (m_video_attributes & VIDEO_VARIABLE_WIDTH);
|
||||
|
||||
switch (curbitmap.format())
|
||||
{
|
||||
case BITMAP_FORMAT_IND16:
|
||||
{
|
||||
bitmap_ind16 &srcbitmap = curbitmap.as_ind16();
|
||||
const u16 src = srcbitmap.pix(y, x);
|
||||
bitmap_ind16 &srcbitmap = per_scanline ? *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y] : curbitmap.as_ind16();
|
||||
const u16 src = per_scanline ? srcbitmap.pix(0, x) : srcbitmap.pix(y, x);
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_adjusted();
|
||||
return (u32)palette[src];
|
||||
}
|
||||
|
||||
case BITMAP_FORMAT_RGB32:
|
||||
{
|
||||
// iterate over rows in the destination
|
||||
bitmap_rgb32 &srcbitmap = curbitmap.as_rgb32();
|
||||
return (u32)srcbitmap.pix(y, x);
|
||||
if (per_scanline)
|
||||
{
|
||||
return (u32)(*(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y]).pix(0, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (u32)curbitmap.as_rgb32().pix(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
@ -1290,15 +1423,17 @@ void screen_device::pixels(u32 *buffer)
|
||||
|
||||
const rectangle &visarea = visible_area();
|
||||
|
||||
const bool per_scanline = (m_video_attributes & VIDEO_VARIABLE_WIDTH);
|
||||
|
||||
switch (curbitmap.format())
|
||||
{
|
||||
case BITMAP_FORMAT_IND16:
|
||||
{
|
||||
bitmap_ind16 &srcbitmap = curbitmap.as_ind16();
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_adjusted();
|
||||
for (int y = visarea.min_y; y <= visarea.max_y; y++)
|
||||
{
|
||||
const u16 *src = &srcbitmap.pix(y, visarea.min_x);
|
||||
bitmap_ind16 &srcbitmap = per_scanline ? *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y] : curbitmap.as_ind16();
|
||||
const u16 *src = &srcbitmap.pix(per_scanline ? 0 : y, visarea.min_x);
|
||||
for (int x = visarea.min_x; x <= visarea.max_x; x++)
|
||||
{
|
||||
*buffer++ = palette[*src++];
|
||||
@ -1309,10 +1444,10 @@ void screen_device::pixels(u32 *buffer)
|
||||
|
||||
case BITMAP_FORMAT_RGB32:
|
||||
{
|
||||
bitmap_rgb32 &srcbitmap = curbitmap.as_rgb32();
|
||||
for (int y = visarea.min_y; y <= visarea.max_y; y++)
|
||||
{
|
||||
const u32 *src = &srcbitmap.pix(y, visarea.min_x);
|
||||
bitmap_rgb32 &srcbitmap = per_scanline ? *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y] : curbitmap.as_rgb32();
|
||||
const u32 *src = &srcbitmap.pix(per_scanline ? 0 : y, visarea.min_x);
|
||||
for (int x = visarea.min_x; x <= visarea.max_x; x++)
|
||||
{
|
||||
*buffer++ = *src++;
|
||||
@ -1508,6 +1643,57 @@ void screen_device::vblank_end()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// create_composited_bitmap - composite scanline
|
||||
// bitmaps into the output bitmap
|
||||
//-------------------------------------------------
|
||||
|
||||
void screen_device::create_composited_bitmap()
|
||||
{
|
||||
screen_bitmap &curbitmap = m_bitmap[m_curtexture];
|
||||
if (!curbitmap.valid())
|
||||
return;
|
||||
|
||||
s32 dstwidth = std::max(m_max_width, m_visarea.right() + 1);
|
||||
int dstheight = curbitmap.height();
|
||||
|
||||
switch (curbitmap.format())
|
||||
{
|
||||
default:
|
||||
case BITMAP_FORMAT_IND16:
|
||||
{
|
||||
for (int y = 0; y < dstheight; y++)
|
||||
{
|
||||
bitmap_ind16 &srcbitmap = *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y];
|
||||
u16 *dst = &curbitmap.as_ind16().pix16(y);
|
||||
const u16 *src = &srcbitmap.pix16(0);
|
||||
const int dx = (m_scan_widths[y] << 15) / dstwidth;
|
||||
for (int x = 0; x < m_scan_widths[y]; x += dx)
|
||||
{
|
||||
*dst++ = src[x >> 15];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case BITMAP_FORMAT_RGB32:
|
||||
{
|
||||
for (int y = 0; y < dstheight; y++)
|
||||
{
|
||||
bitmap_rgb32 &srcbitmap = *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y];
|
||||
u32 *dst = &curbitmap.as_rgb32().pix32(y);
|
||||
const u32 *src = &srcbitmap.pix32(0);
|
||||
const int dx = (m_scan_widths[y] << 15) / dstwidth;
|
||||
for (int x = 0; x < dstwidth << 15; x += dx)
|
||||
{
|
||||
*dst++ = src[x >> 15];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// update_quads - set up the quads for this
|
||||
// screen
|
||||
@ -1524,6 +1710,10 @@ bool screen_device::update_quads()
|
||||
// if we're not skipping the frame and if the screen actually changed, then update the texture
|
||||
if (!machine().video().skip_this_frame() && m_changed)
|
||||
{
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
create_composited_bitmap();
|
||||
}
|
||||
m_texture[m_curbitmap]->set_bitmap(m_bitmap[m_curbitmap], m_visarea, m_bitmap[m_curbitmap].texformat());
|
||||
m_curtexture = m_curbitmap;
|
||||
m_curbitmap = 1 - m_curbitmap;
|
||||
@ -1568,8 +1758,8 @@ void screen_device::update_burnin()
|
||||
int ystep = (srcheight << 16) / dstheight;
|
||||
int xstart = (u32(rand()) % 32767) * xstep / 32767;
|
||||
int ystart = (u32(rand()) % 32767) * ystep / 32767;
|
||||
int srcx, srcy;
|
||||
int x, y;
|
||||
|
||||
bool per_scanline = (m_video_attributes & VIDEO_VARIABLE_WIDTH);
|
||||
|
||||
switch (curbitmap.format())
|
||||
{
|
||||
@ -1577,13 +1767,13 @@ void screen_device::update_burnin()
|
||||
case BITMAP_FORMAT_IND16:
|
||||
{
|
||||
// iterate over rows in the destination
|
||||
bitmap_ind16 &srcbitmap = curbitmap.as_ind16();
|
||||
for (y = 0, srcy = ystart; y < dstheight; y++, srcy += ystep)
|
||||
for (int y = 0, srcy = ystart; y < dstheight; y++, srcy += ystep)
|
||||
{
|
||||
bitmap_ind16 &srcbitmap = per_scanline ? *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y] : curbitmap.as_ind16();
|
||||
u64 *dst = &m_burnin.pix64(y);
|
||||
const u16 *src = &srcbitmap.pix16(srcy >> 16);
|
||||
const u16 *src = &srcbitmap.pix16(per_scanline ? 0 : (srcy >> 16));
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_adjusted();
|
||||
for (x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
|
||||
for (int x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
|
||||
{
|
||||
rgb_t pixel = palette[src[srcx >> 16]];
|
||||
dst[x] += pixel.g() + pixel.r() + pixel.b();
|
||||
@ -1595,12 +1785,12 @@ void screen_device::update_burnin()
|
||||
case BITMAP_FORMAT_RGB32:
|
||||
{
|
||||
// iterate over rows in the destination
|
||||
bitmap_rgb32 &srcbitmap = curbitmap.as_rgb32();
|
||||
for (y = 0, srcy = ystart; y < dstheight; y++, srcy += ystep)
|
||||
for (int y = 0, srcy = ystart; y < dstheight; y++, srcy += ystep)
|
||||
{
|
||||
bitmap_rgb32 &srcbitmap = per_scanline ? *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y] : curbitmap.as_rgb32();
|
||||
u64 *dst = &m_burnin.pix64(y);
|
||||
const u32 *src = &srcbitmap.pix32(srcy >> 16);
|
||||
for (x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
|
||||
const u32 *src = &srcbitmap.pix32(per_scanline ? 0 : (srcy >> 16));
|
||||
for (int x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
|
||||
{
|
||||
rgb_t pixel = src[srcx >> 16];
|
||||
dst[x] += pixel.g() + pixel.r() + pixel.b();
|
||||
|
@ -63,6 +63,9 @@ constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed
|
||||
@def VIDEO_UPDATE_SCANLINE
|
||||
calls VIDEO_UPDATE for every visible scanline, even for skipped frames
|
||||
|
||||
@def VIDEO_VARIABLE_WIDTH
|
||||
causes the screen to construct its final bitmap from a composite upscale of individual scanline bitmaps
|
||||
|
||||
@}
|
||||
*/
|
||||
|
||||
@ -72,6 +75,7 @@ constexpr u32 VIDEO_UPDATE_AFTER_VBLANK = 0x0004;
|
||||
constexpr u32 VIDEO_SELF_RENDER = 0x0008;
|
||||
constexpr u32 VIDEO_ALWAYS_UPDATE = 0x0080;
|
||||
constexpr u32 VIDEO_UPDATE_SCANLINE = 0x0100;
|
||||
constexpr u32 VIDEO_VARIABLE_WIDTH = 0x0200;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -182,7 +186,7 @@ public:
|
||||
set_type(type);
|
||||
set_color(color);
|
||||
}
|
||||
~screen_device();
|
||||
virtual ~screen_device();
|
||||
|
||||
// configuration readers
|
||||
screen_type_enum screen_type() const { return m_type; }
|
||||
@ -224,7 +228,7 @@ public:
|
||||
/// \param [in] vbstart Index of first line in vertical blanking
|
||||
/// period after visible lines.
|
||||
/// \return Reference to device for method chaining.
|
||||
screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
|
||||
virtual screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
|
||||
{
|
||||
assert(pixclock != 0);
|
||||
m_clock = pixclock;
|
||||
@ -389,7 +393,7 @@ public:
|
||||
|
||||
// beam positioning and state
|
||||
int vpos() const;
|
||||
int hpos() const;
|
||||
virtual int hpos() const;
|
||||
DECLARE_READ_LINE_MEMBER(vblank) const { return (machine().time() < m_vblank_end_time) ? 1 : 0; }
|
||||
DECLARE_READ_LINE_MEMBER(hblank) const { int const curpos = hpos(); return (curpos < m_visarea.left() || curpos > m_visarea.right()) ? 1 : 0; }
|
||||
|
||||
@ -403,14 +407,14 @@ public:
|
||||
u64 frame_number() const { return m_frame_number; }
|
||||
|
||||
// pixel-level access
|
||||
u32 pixel(s32 x, s32 y);
|
||||
void pixels(u32* buffer);
|
||||
virtual u32 pixel(s32 x, s32 y);
|
||||
virtual void pixels(u32* buffer);
|
||||
|
||||
// updating
|
||||
int partial_updates() const { return m_partial_updates_this_frame; }
|
||||
bool update_partial(int scanline);
|
||||
void update_now();
|
||||
void reset_partial_updates();
|
||||
virtual bool update_partial(int scanline);
|
||||
virtual void update_now();
|
||||
virtual void reset_partial_updates();
|
||||
|
||||
// additional helpers
|
||||
void register_vblank_callback(vblank_state_delegate vblank_callback);
|
||||
@ -424,7 +428,9 @@ public:
|
||||
static constexpr int DEFAULT_FRAME_RATE = 60;
|
||||
static const attotime DEFAULT_FRAME_PERIOD;
|
||||
|
||||
private:
|
||||
protected:
|
||||
screen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
class svg_renderer;
|
||||
|
||||
// timer IDs
|
||||
@ -453,6 +459,9 @@ private:
|
||||
void vblank_end();
|
||||
void finalize_burnin();
|
||||
void load_effect_overlay(const char *filename);
|
||||
void update_scan_bitmap_size(int y);
|
||||
void pre_update_scanline(int y);
|
||||
void create_composited_bitmap();
|
||||
|
||||
// inline configuration data
|
||||
screen_type_enum m_type; // type of screen
|
||||
@ -475,14 +484,17 @@ private:
|
||||
render_container * m_container; // pointer to our container
|
||||
std::unique_ptr<svg_renderer> m_svg; // the svg renderer
|
||||
// dimensions
|
||||
int m_max_width; // maximum width encountered
|
||||
int m_width; // current width (HTOTAL)
|
||||
int m_height; // current height (VTOTAL)
|
||||
rectangle m_visarea; // current visible area (HBLANK end/start, VBLANK end/start)
|
||||
std::vector<int> m_scan_widths; // current width, in samples, of each individual scanline
|
||||
|
||||
// textures and bitmaps
|
||||
texture_format m_texformat; // texture format
|
||||
render_texture * m_texture[2]; // 2x textures for the screen bitmap
|
||||
screen_bitmap m_bitmap[2]; // 2x bitmaps for rendering
|
||||
std::vector<bitmap_t *> m_scan_bitmaps[2]; // 2x bitmaps for each individual scanline
|
||||
bitmap_ind8 m_priority; // priority bitmap
|
||||
bitmap_ind64 m_burnin; // burn-in bitmap
|
||||
u8 m_curbitmap; // current bitmap index
|
||||
|
@ -38,6 +38,7 @@ constexpr int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2;
|
||||
class video_manager
|
||||
{
|
||||
friend class screen_device;
|
||||
friend class variable_width_screen_device;
|
||||
|
||||
public:
|
||||
// movie format options
|
||||
|
@ -1351,6 +1351,7 @@ void snes_console_state::snes(machine_config &config)
|
||||
/* video hardware */
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_raw(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC);
|
||||
m_screen->set_video_attributes(VIDEO_VARIABLE_WIDTH);
|
||||
m_screen->set_screen_update(FUNC(snes_state::screen_update));
|
||||
|
||||
SNES_PPU(config, m_ppu, MCLK_NTSC);
|
||||
|
@ -235,7 +235,7 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_hblank_tick)
|
||||
hdma(cpu0space);
|
||||
|
||||
if (m_screen->vpos() > 0)
|
||||
m_screen->update_partial((m_ppu->interlace() == 2) ? (m_ppu->current_vert() * m_ppu->interlace()) : m_ppu->current_vert());
|
||||
m_screen->update_partial((m_ppu->interlace() == 2) ? (m_ppu->current_vert() * m_ppu->interlace()) : m_ppu->current_vert() - 1);
|
||||
}
|
||||
|
||||
// signal hblank
|
||||
@ -1035,7 +1035,7 @@ void snes_state::snes_init_timers()
|
||||
|
||||
// SNES hcounter has a 0-339 range. hblank starts at counter 260.
|
||||
// clayfighter sets an HIRQ at 260, apparently it wants it to be before hdma kicks off, so we'll delay 2 pixels.
|
||||
m_hblank_offset = 128;
|
||||
m_hblank_offset = 274;
|
||||
m_hblank_timer->adjust(m_screen->time_until_pos(m_ppu->vtotal() - 1, m_hblank_offset));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user