From 100767b3df9192de04b7df772360311f141c7eab Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Thu, 24 Oct 2019 18:52:15 +0200 Subject: -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] --- src/emu/screen.cpp | 298 +++++++++++++++++++++++++++++++++++++++++++---------- src/emu/screen.h | 30 ++++-- src/emu/video.h | 1 + 3 files changed, 266 insertions(+), 63 deletions(-) (limited to 'src/emu') diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index db6f7c91ad4..7a342662c56 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -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) + { + 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 { - 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; + 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(); diff --git a/src/emu/screen.h b/src/emu/screen.h index 6754d66f071..cf6201b4acf 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -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 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 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 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 diff --git a/src/emu/video.h b/src/emu/video.h index b8b1c408773..6015eecf146 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -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 -- cgit v1.2.3