mirror of
https://github.com/holub/mame
synced 2025-07-02 00:29:37 +03:00
Added a fixed frequency monitor emulation to src/emu/video.
This implementation takes an analog composite signal, extracts hsync, vsync and field information in addition to greyscale video. Currently needed for pong.
This commit is contained in:
parent
ab4939c07e
commit
f28956e82d
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1886,6 +1886,8 @@ src/emu/video/dm9368.h svneol=native#text/plain
|
||||
src/emu/video/ef9340_1.c svneol=native#text/plain
|
||||
src/emu/video/ef9340_1.h svneol=native#text/plain
|
||||
src/emu/video/ef9341_chargen.h svneol=native#text/plain
|
||||
src/emu/video/fixfreq.c svneol=native#text/plain
|
||||
src/emu/video/fixfreq.h svneol=native#text/plain
|
||||
src/emu/video/generic.c svneol=native#text/plain
|
||||
src/emu/video/generic.h svneol=native#text/plain
|
||||
src/emu/video/h63484.c svneol=native#text/plain
|
||||
|
276
src/emu/video/fixfreq.c
Normal file
276
src/emu/video/fixfreq.c
Normal file
@ -0,0 +1,276 @@
|
||||
/***************************************************************************
|
||||
|
||||
fixfreq.h
|
||||
|
||||
2013 Couriersud
|
||||
|
||||
Fixed frequency monochrome monitor emulation
|
||||
|
||||
The driver is intended for drivers which provide an analog video signal.
|
||||
VSYNC and HSYNC levels are used to create the bitmap.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "fixfreq.h"
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Local variables
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
//#define VERBOSE_OUT(x) printf x
|
||||
#define VERBOSE_OUT(x)
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Static declarations
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
//ModeLine "720x480@30i" 13.5 720 736 799 858 480 486 492 525 interlace -hsync -vsync
|
||||
fixedfreq_interface fixedfreq_mode_ntsc720 = {
|
||||
13500000,
|
||||
720,736,799,858,
|
||||
480,486,492,525,
|
||||
2, /* interlaced */
|
||||
0.3
|
||||
};
|
||||
|
||||
//ModeLine "704x480@30i" 13.5 704 728 791 858 480 486 492 525
|
||||
fixedfreq_interface fixedfreq_mode_ntsc704 = {
|
||||
13500000,
|
||||
704,728,791,858,
|
||||
480,486,492,525,
|
||||
2, /* interlaced */
|
||||
0.3
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Fixed frequency monitor
|
||||
|
||||
***************************************************************************/
|
||||
// device type definition
|
||||
const device_type FIXFREQ = &device_creator<fixedfreq_device>;
|
||||
|
||||
fixedfreq_device::fixedfreq_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||
device_video_interface(mconfig, *this, false)
|
||||
{
|
||||
}
|
||||
|
||||
fixedfreq_device::fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, FIXFREQ, "FIXFREQ", tag, owner, clock, "fixfreq", __FILE__),
|
||||
device_video_interface(mconfig, *this, false)
|
||||
{
|
||||
}
|
||||
|
||||
void fixedfreq_device::device_config_complete()
|
||||
{
|
||||
const fixedfreq_interface *intf = reinterpret_cast<const fixedfreq_interface *>(static_config());
|
||||
|
||||
if ( intf != NULL )
|
||||
{
|
||||
*static_cast<fixedfreq_interface *>(this) = *intf;
|
||||
}
|
||||
else
|
||||
{
|
||||
*static_cast<fixedfreq_interface *>(this) = fixedfreq_mode_ntsc704;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void fixedfreq_device::device_start()
|
||||
{
|
||||
m_cur_bm = 0;
|
||||
m_vid = 0.0;
|
||||
m_vint = 0.0;
|
||||
m_last_x = 0;
|
||||
m_last_y = 0;
|
||||
m_refresh = attotime::zero;
|
||||
m_bitmap[0] = NULL;
|
||||
m_bitmap[1] = NULL;
|
||||
m_last_time = attotime::zero;
|
||||
m_last_hsync_time = attotime::zero;
|
||||
m_last_vsync_time = attotime::zero;
|
||||
//m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
|
||||
recompute_parameters(false);
|
||||
|
||||
m_sig_vsync = 0;
|
||||
m_sig_composite = 0;
|
||||
m_sig_field = 0;
|
||||
}
|
||||
|
||||
void fixedfreq_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void fixedfreq_device::device_post_load()
|
||||
{
|
||||
//recompute_parameters(true);
|
||||
}
|
||||
|
||||
void fixedfreq_device::recompute_parameters(bool postload)
|
||||
{
|
||||
bool needs_realloc = (m_htotal != m_hbackporch) && (m_vtotal != m_vbackporch);
|
||||
|
||||
if (m_bitmap[0] != NULL || needs_realloc)
|
||||
auto_free(machine(), m_bitmap[0]);
|
||||
if (m_bitmap[1] != NULL || needs_realloc)
|
||||
auto_free(machine(), m_bitmap[0]);
|
||||
|
||||
m_htotal = m_hbackporch;
|
||||
m_vtotal = m_vbackporch;
|
||||
|
||||
/* sync separator */
|
||||
|
||||
m_int_trig = (exp(- 3.0/(3.0+3.0))) - exp(-1.0);
|
||||
m_mult = (double) (m_monitor_clock) / m_htotal; // / (3.0 + 3.0);
|
||||
VERBOSE_OUT(("trigger %f with len %f\n", m_int_trig, 1e6 / m_mult));
|
||||
|
||||
m_bitmap[0] = auto_bitmap_rgb32_alloc(machine(),m_htotal, m_vtotal);
|
||||
m_bitmap[1] = auto_bitmap_rgb32_alloc(machine(),m_htotal, m_vtotal);
|
||||
|
||||
rectangle visarea(
|
||||
m_hbackporch - m_hfrontporch,
|
||||
m_hbackporch - m_hfrontporch + m_hvisible - 1,
|
||||
m_vbackporch - m_vfrontporch,
|
||||
m_vbackporch - m_vfrontporch + m_vvisible - 1);
|
||||
|
||||
m_clock_period = attotime::from_hz(m_monitor_clock);
|
||||
|
||||
m_refresh = attotime::from_hz(m_monitor_clock) * m_vtotal * m_htotal;
|
||||
screen().configure(m_htotal, m_vtotal, visarea, m_refresh.as_attoseconds());
|
||||
}
|
||||
|
||||
void fixedfreq_device::update_screen_parameters(attotime refresh)
|
||||
{
|
||||
rectangle visarea(
|
||||
// m_hsync - m_hvisible,
|
||||
// m_hsync - 1 ,
|
||||
m_hbackporch - m_hfrontporch,
|
||||
m_hbackporch - m_hfrontporch + m_hvisible - 1,
|
||||
m_vbackporch - m_vfrontporch,
|
||||
m_vbackporch - m_vfrontporch + m_vvisible - 1);
|
||||
|
||||
m_refresh = refresh;
|
||||
screen().configure(m_htotal, m_vtotal, visarea, m_refresh.as_attoseconds());
|
||||
}
|
||||
|
||||
int fixedfreq_device::sync_separator(attotime time, double newval)
|
||||
{
|
||||
int last_vsync = m_sig_vsync;
|
||||
int last_comp = m_sig_composite;
|
||||
int ret = 0;
|
||||
|
||||
m_vint += ((double) m_sig_composite - m_vint) * (1.0 - exp(-time.as_double() * m_mult));
|
||||
m_sig_composite = (newval < m_sync_threshold) ? 1 : 0 ;
|
||||
|
||||
m_sig_vsync = (m_vint > m_int_trig) ? 1 : 0;
|
||||
|
||||
if (!last_vsync && m_sig_vsync)
|
||||
{
|
||||
/* TODO - time since last hsync and field detection */
|
||||
ret |= 1;
|
||||
}
|
||||
if (last_vsync && !m_sig_vsync)
|
||||
{
|
||||
m_sig_field = last_comp; /* force false-progressive */
|
||||
m_sig_field = (m_sig_field ^ 1) ^ last_comp; /* if there is no field switch, auto switch */
|
||||
VERBOSE_OUT(("Field: %d\n", m_sig_field));
|
||||
}
|
||||
if (!last_comp && m_sig_composite)
|
||||
{
|
||||
/* TODO - time since last hsync and field detection */
|
||||
ret |= 2;
|
||||
}
|
||||
if (last_comp && !m_sig_composite)
|
||||
{
|
||||
/* falling composite */
|
||||
ret |= 4;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT32 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fixedfreq_device::update_vid(double newval, attotime cur_time)
|
||||
{
|
||||
|
||||
static attotime m_last_time = attotime(0,0);
|
||||
static attotime m_line_time = attotime(0,0);
|
||||
|
||||
|
||||
bitmap_rgb32 *bm = m_bitmap[m_cur_bm];
|
||||
|
||||
int pixels = round((cur_time - m_line_time).as_double() / m_clock_period.as_double());
|
||||
attotime time = (cur_time - m_last_time);
|
||||
|
||||
if ((newval == m_vid))
|
||||
return;
|
||||
|
||||
ATTR_UNUSED int sync = sync_separator(time, newval);
|
||||
|
||||
if (m_last_y < bm->height())
|
||||
{
|
||||
rgb_t col;
|
||||
if (m_vid < m_sync_threshold)
|
||||
col = MAKE_RGB(255, 0, 0);
|
||||
else
|
||||
{
|
||||
int colv = (int) ((m_vid - m_sync_threshold) / 3.2 * 255.0);
|
||||
col = MAKE_RGB(colv, colv, colv);
|
||||
}
|
||||
|
||||
if (m_vid < m_sync_threshold)
|
||||
|
||||
while (0 && pixels >= m_htotal)
|
||||
{
|
||||
bm->plot_box(m_last_x, m_last_y + m_sig_field, m_htotal - 1 - m_last_x, 1, col);
|
||||
pixels -= m_htotal;
|
||||
m_last_x = 0;
|
||||
}
|
||||
bm->plot_box(m_last_x, m_last_y + m_sig_field, pixels - m_last_x, 1, col);
|
||||
m_last_x = pixels;
|
||||
}
|
||||
if (sync & 1) VERBOSE_OUT(("VSYNC %d %d\n", pixels, m_last_y + m_sig_field));
|
||||
if (sync & 2)
|
||||
VERBOSE_OUT(("HSYNC up %d\n", pixels));
|
||||
if (sync & 4)
|
||||
VERBOSE_OUT(("HSYNC down %f %d %f\n", time.as_double()* 1e6, pixels, m_vid));
|
||||
//VERBOSE_OUT(("%d\n", m_last_x);
|
||||
|
||||
if (sync & 1)
|
||||
{
|
||||
m_last_y = 0;
|
||||
// toggle bitmap
|
||||
m_cur_bm ^= 1;
|
||||
update_screen_parameters(cur_time - m_last_vsync_time);
|
||||
m_last_vsync_time = cur_time;
|
||||
}
|
||||
|
||||
if (sync & 2)
|
||||
{
|
||||
m_last_y += m_fieldcount;
|
||||
m_last_x = 0;
|
||||
m_line_time = cur_time;
|
||||
}
|
||||
|
||||
m_last_time = cur_time;
|
||||
m_vid = newval;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
108
src/emu/video/fixfreq.h
Normal file
108
src/emu/video/fixfreq.h
Normal file
@ -0,0 +1,108 @@
|
||||
/***************************************************************************
|
||||
|
||||
fixfreq.h
|
||||
|
||||
Fixed frequency monochrome monitor emulation
|
||||
|
||||
The driver is intended for drivers which provide an analog video signal.
|
||||
VSYNC and HSYNC levels are used to create the bitmap.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FIXFREQ_H
|
||||
#define FIXFREQ_H
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#define FIXFREQ_INTERFACE(name) \
|
||||
const fixedfreq_interface (name) =
|
||||
|
||||
#define MCFG_FIXFREQ_ADD(_tag, _screen_tag, _config) \
|
||||
MCFG_SCREEN_ADD(_screen_tag, RASTER) \
|
||||
MCFG_SCREEN_RAW_PARAMS(13500000, 858, 0, 858, 525, 0, 525) \
|
||||
MCFG_SCREEN_UPDATE_DEVICE(_tag, fixedfreq_device, screen_update) \
|
||||
MCFG_DEVICE_ADD(_tag, FIXFREQ, 0) \
|
||||
MCFG_VIDEO_SET_SCREEN(_screen_tag) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
struct fixedfreq_interface {
|
||||
UINT32 m_monitor_clock;
|
||||
int m_hvisible;
|
||||
int m_hfrontporch;
|
||||
int m_hsync;
|
||||
int m_hbackporch;
|
||||
int m_vvisible;
|
||||
int m_vfrontporch;
|
||||
int m_vsync;
|
||||
int m_vbackporch;
|
||||
int m_fieldcount;
|
||||
double m_sync_threshold;
|
||||
};
|
||||
|
||||
extern fixedfreq_interface fixedfreq_mode_ntsc704;
|
||||
extern fixedfreq_interface fixedfreq_mode_ntsc720;
|
||||
|
||||
// ======================> vga_device
|
||||
|
||||
class fixedfreq_device : public device_t,
|
||||
public device_video_interface,
|
||||
public fixedfreq_interface
|
||||
{
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
fixedfreq_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
||||
|
||||
|
||||
virtual UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void update_vid(const double newval, const attotime cur_time);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_post_load();
|
||||
//virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
void recompute_parameters(bool postload);
|
||||
void update_screen_parameters(attotime refresh);
|
||||
|
||||
private:
|
||||
|
||||
int sync_separator(attotime time, double newval);
|
||||
|
||||
int m_htotal;
|
||||
int m_vtotal;
|
||||
|
||||
double m_vid;
|
||||
int m_last_x;
|
||||
int m_last_y;
|
||||
attotime m_last_time;
|
||||
attotime m_last_hsync_time;
|
||||
attotime m_last_vsync_time;
|
||||
attotime m_refresh;
|
||||
attotime m_clock_period;
|
||||
bitmap_rgb32 *m_bitmap[2];
|
||||
int m_cur_bm;
|
||||
|
||||
/* sync separator */
|
||||
double m_vint;
|
||||
double m_int_trig;
|
||||
double m_mult;
|
||||
|
||||
int m_sig_vsync;
|
||||
int m_sig_composite;
|
||||
int m_sig_field;
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type FIXFREQ;
|
||||
|
||||
#endif /* FIXFREQ_H */
|
@ -104,6 +104,15 @@ ifneq ($(filter EF9340_1,$(VIDEOS)),)
|
||||
VIDEOOBJS+= $(VIDEOOBJ)/ef9340_1.o
|
||||
endif
|
||||
|
||||
#-------------------------------------------------
|
||||
#
|
||||
#@src/emu/video/fixfreq.h,VIDEOS += FIXFREQ
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter FIXFREQ,$(VIDEOS)),)
|
||||
VIDEOOBJS+= $(VIDEOOBJ)/fixfreq.o
|
||||
endif
|
||||
|
||||
#-------------------------------------------------
|
||||
#
|
||||
#@src/emu/video/h63484.h,VIDEOS += H63484
|
||||
|
Loading…
Reference in New Issue
Block a user