mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
netlist video: Add VECTOR support. [Couriersud]
Fixfreq now supports VECTOR screens automatically. For now the default remains to be RASTER since bgfx does not support VECTOR screens. Nevertheless please expect changes in the video output. Video output is now collected timing-exact, i.e. with subpixel accuracy. Only during screen_update this is converted and scaled to the bitmap. There may be changes due to rounding in comparison to current rendering. Also added a link to a video showing a breakout cocktail table.
This commit is contained in:
parent
1ac2d06ea1
commit
6b004964ef
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "rendutil.h"
|
||||
#include "fixfreq.h"
|
||||
|
||||
//#define VERBOSE 1
|
||||
@ -83,7 +84,7 @@ void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const d
|
||||
|
||||
void fixedfreq_monitor_state::update_bm(const time_type &time)
|
||||
{
|
||||
const int pixels = round((time - m_line_time) * m_desc.m_hscale / m_clock_period);
|
||||
const float pixels = (time - m_line_time) * static_cast<time_type>(m_desc.m_hscale) / m_clock_period;
|
||||
const int has_fields = (m_desc.m_fieldcount > 1) ? 1: 0;
|
||||
|
||||
uint32_t col(0xffff0000); // Mark sync areas
|
||||
@ -91,7 +92,8 @@ void fixedfreq_monitor_state::update_bm(const time_type &time)
|
||||
if (m_sync_signal >= m_desc.m_sync_threshold)
|
||||
col = m_col;
|
||||
|
||||
m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, col);
|
||||
m_fragments.push_back({static_cast<float>(m_last_y + m_sig_field * has_fields), m_last_x, pixels, col});
|
||||
//m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels, col);
|
||||
m_last_x = pixels;
|
||||
}
|
||||
|
||||
@ -157,7 +159,6 @@ void fixedfreq_monitor_state::update_sync(const time_type &time, const double da
|
||||
fixedfreq_device::fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock),
|
||||
device_video_interface(mconfig, *this, false),
|
||||
m_cur_bm(0),
|
||||
m_htotal(0),
|
||||
m_vtotal(0),
|
||||
m_refresh_period(time_type(0)),
|
||||
@ -190,12 +191,8 @@ void fixedfreq_device::device_start()
|
||||
|
||||
m_refresh_period = time_type(0);
|
||||
|
||||
m_cur_bm = 0;
|
||||
|
||||
m_htotal = m_monitor.m_hbackporch;
|
||||
m_vtotal = m_monitor.m_vbackporch;
|
||||
m_bitmap[0] = std::make_unique<bitmap_rgb32>(m_htotal * m_monitor.m_hscale, m_vtotal);
|
||||
m_bitmap[1] = std::make_unique<bitmap_rgb32>(m_htotal * m_monitor.m_hscale, m_vtotal);
|
||||
|
||||
m_state.start();
|
||||
|
||||
@ -209,9 +206,6 @@ void fixedfreq_device::device_start()
|
||||
save_item(NAME(m_state.m_last_vsync_time));
|
||||
save_item(NAME(m_refresh_period));
|
||||
save_item(NAME(m_state.m_clock_period));
|
||||
//save_item(NAME(m_bitmap[0]));
|
||||
//save_item(NAME(m_bitmap[1]));
|
||||
save_item(NAME(m_cur_bm));
|
||||
|
||||
/* sync separator */
|
||||
save_item(NAME(m_state.m_vsync_filter));
|
||||
@ -235,15 +229,45 @@ void fixedfreq_device::device_post_load()
|
||||
|
||||
uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, *m_bitmap[!m_cur_bm], 0, 0, 0, 0, cliprect);
|
||||
|
||||
if (screen.screen_type() == SCREEN_TYPE_RASTER)
|
||||
{
|
||||
for (auto &f : m_state.m_fragments)
|
||||
if (f.y < bitmap.height())
|
||||
bitmap.plot_box(f.x, f.y, f.xr - f.x, 1, f.col);
|
||||
}
|
||||
else if (screen.screen_type() == SCREEN_TYPE_VECTOR)
|
||||
{
|
||||
constexpr const uint32_t flags(PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTOR(1));
|
||||
const rectangle &visarea = screen.visible_area();
|
||||
float xscale = 1.0f / visarea.width();
|
||||
float yscale = 1.0f / visarea.height();
|
||||
float xoffs = (float)visarea.min_x;
|
||||
float yoffs = (float)visarea.min_y;
|
||||
screen.container().empty();
|
||||
screen.container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTORBUF(1));
|
||||
|
||||
for (auto &f : m_state.m_fragments)
|
||||
{
|
||||
const float x0((f.x - xoffs) * xscale);
|
||||
const float y0((f.y - yoffs) * yscale);
|
||||
const float x1((f.xr - xoffs) * xscale);
|
||||
const float y1((f.y + 1.0f - yoffs) * yscale);
|
||||
|
||||
screen.container().add_rect(
|
||||
x0, y0, x1, y1,
|
||||
(0xff << 24) | (f.col & 0xffffff),
|
||||
flags);
|
||||
}
|
||||
}
|
||||
m_state.m_fragments.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fixedfreq_device::vsync_start_cb(double refresh_time)
|
||||
{
|
||||
// toggle bitmap
|
||||
m_cur_bm ^= 1;
|
||||
//m_cur_bm ^= 1;
|
||||
|
||||
rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), m_monitor.maxv());
|
||||
|
||||
@ -251,13 +275,6 @@ void fixedfreq_device::vsync_start_cb(double refresh_time)
|
||||
screen().configure(m_htotal * m_monitor.m_hscale, m_vtotal, visarea, DOUBLE_TO_ATTOSECONDS(m_refresh_period));
|
||||
}
|
||||
|
||||
void fixedfreq_device::plot_hline(int x, int y, int w, uint32_t col)
|
||||
{
|
||||
bitmap_rgb32 *bm = m_bitmap[m_cur_bm].get();
|
||||
if (y < bm->height())
|
||||
bm->plot_box(x, y, w, 1, col);
|
||||
}
|
||||
|
||||
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome)
|
||||
{
|
||||
// double is good enough for this exercise;
|
||||
|
@ -60,7 +60,14 @@ struct fixedfreq_monitor_intf
|
||||
{
|
||||
virtual ~fixedfreq_monitor_intf() = default;
|
||||
virtual void vsync_start_cb(double refresh_time) = 0;
|
||||
virtual void plot_hline(int x, int y, int w, uint32_t col) = 0;
|
||||
};
|
||||
|
||||
struct fixedfreq_monitor_line
|
||||
{
|
||||
float y;
|
||||
float x;
|
||||
float xr;
|
||||
uint32_t col;
|
||||
};
|
||||
|
||||
struct fixedfreq_monitor_state
|
||||
@ -127,8 +134,10 @@ struct fixedfreq_monitor_state
|
||||
m_clock_period = 1.0 / m_desc.m_monitor_clock;
|
||||
// Minimum frame period to be passed to video system ?
|
||||
m_min_frame_period = 0.25 * m_clock_period * m_desc.m_vbackporch * m_desc.m_hbackporch;
|
||||
m_intf.vsync_start_cb(m_min_frame_period);
|
||||
|
||||
m_fragments.clear();
|
||||
|
||||
m_intf.vsync_start_cb(m_min_frame_period);
|
||||
}
|
||||
|
||||
void reset()
|
||||
@ -148,6 +157,7 @@ struct fixedfreq_monitor_state
|
||||
m_sig_vsync = 0;
|
||||
m_sig_composite = 0;
|
||||
m_sig_field = 0;
|
||||
m_fragments.clear();
|
||||
}
|
||||
|
||||
void update_sync_channel(const time_type &time, const double newval);
|
||||
@ -163,7 +173,7 @@ struct fixedfreq_monitor_state
|
||||
|
||||
double m_sync_signal;
|
||||
uint32_t m_col;
|
||||
int m_last_x;
|
||||
float m_last_x;
|
||||
int m_last_y;
|
||||
time_type m_last_sync_time;
|
||||
time_type m_line_time;
|
||||
@ -180,6 +190,7 @@ struct fixedfreq_monitor_state
|
||||
int m_sig_composite;
|
||||
int m_sig_field;
|
||||
time_type m_min_frame_period;
|
||||
std::vector<fixedfreq_monitor_line> m_fragments;
|
||||
};
|
||||
|
||||
// ======================> fixedfreq_device
|
||||
@ -254,12 +265,9 @@ protected:
|
||||
//virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
void vsync_start_cb(double refresh_time) override;
|
||||
void plot_hline(int x, int y, int w, uint32_t col) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<bitmap_rgb32> m_bitmap[2];
|
||||
int m_cur_bm;
|
||||
int m_htotal;
|
||||
int m_vtotal;
|
||||
|
||||
|
@ -97,6 +97,12 @@ TODO: Volleyball...
|
||||
* https://www.youtube.com/watch?v=pDrRnJOCKZc (no longer available)
|
||||
*
|
||||
* https://www.youtube.com/watch?v=fiShX2pTz9A
|
||||
* https://www.youtube.com/watch?v=YmzH4E3x1_g
|
||||
*
|
||||
* Breakout videos:
|
||||
*
|
||||
* https://www.youtube.com/watch?v=NOGO49j5gCE
|
||||
*
|
||||
*/
|
||||
|
||||
static const int NS_PER_CLOCK_PONG = static_cast<int>((double) NETLIST_INTERNAL_RES / (double) 7159000 + 0.5);
|
||||
@ -483,6 +489,7 @@ void pong_state::pong(machine_config &config)
|
||||
|
||||
/* video hardware */
|
||||
SCREEN(config, "screen", SCREEN_TYPE_RASTER);
|
||||
//SCREEN(config, "screen", SCREEN_TYPE_VECTOR);
|
||||
FIXFREQ(config, m_video).set_screen("screen");
|
||||
m_video->set_monitor_clock(MASTER_CLOCK_PONG);
|
||||
m_video->set_horz_params(H_TOTAL_PONG-67,H_TOTAL_PONG-40,H_TOTAL_PONG-8,H_TOTAL_PONG);
|
||||
@ -533,8 +540,9 @@ void breakout_state::breakout(machine_config &config)
|
||||
NETLIST_ANALOG_OUTPUT(config, "maincpu:coin_counter", 0).set_params("CON_T", FUNC(breakout_state::coin_counter_cb));
|
||||
|
||||
/* video hardware */
|
||||
SCREEN(config, "screen", SCREEN_TYPE_RASTER);
|
||||
FIXFREQ(config, m_video).set_screen("screen");
|
||||
SCREEN(config, "screen", SCREEN_TYPE_RASTER);
|
||||
//SCREEN(config, "screen", SCREEN_TYPE_VECTOR);
|
||||
/* The Pixel width is a 2,1,2,1,2,1,1,1 repeating pattern
|
||||
* Thus we must use double resolution horizontally
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user