summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author dave-br <dave-br@users.noreply.github.com>2023-12-22 06:23:13 -0800
committer GitHub <noreply@github.com>2023-12-23 01:23:13 +1100
commitb0c924a959a17f68a6dafd06bf17bb4f1f44e0e1 (patch)
tree26da2ef19a7fbe4c33177068c049b51217f21286
parenta52925516e8ce57fe741c8864b6dc039b7a3d10e (diff)
video/mc6847.cpp: Fixed synchronization on Dragon (PAL) machines. (#11743)
-rw-r--r--src/devices/video/mc6847.cpp272
-rw-r--r--src/devices/video/mc6847.h23
-rw-r--r--src/mame/trs/coco3.cpp2
-rw-r--r--src/mame/trs/dragon.cpp2
-rw-r--r--src/mame/trs/gime.cpp12
-rw-r--r--src/mame/trs/gime.h4
6 files changed, 205 insertions, 110 deletions
diff --git a/src/devices/video/mc6847.cpp b/src/devices/video/mc6847.cpp
index 0d347eb1ed9..84597c33c11 100644
--- a/src/devices/video/mc6847.cpp
+++ b/src/devices/video/mc6847.cpp
@@ -67,8 +67,25 @@
if skew existed. SockMaster has confirmed that scanlines are in
fact 228 clock cycles.
- The PAL emulation is little more than having more scanlines; surely
- there are details that we are missing here.
+ PAL info from chats with Ciaran (XRoar) and from his page
+ https://www.6809.org.uk/dragon/hardware.shtml :
+ The 6847 does not directly support PAL, but many PAL machines
+ with a 6847 add circuitry to stuff scalines into the frame,
+ to pad it out to be consistent with PAL CRTs. This padding
+ consists of a top and bottom region of black lines. Some
+ Dragon 64s turn off HS during the padding; other Dragons enable
+ HS all the way. Some Dragons use the same 14.31818MHz crystal
+ as NTSC machines; other Dragons use 14.218MHz. In either case,
+ the 6847, 6883 (SAM), and 6809 (CPU) base their timings on the
+ same crystal (divided appropriately).
+
+ Many of the cycle counts below were derived via experimentation
+ with coco_cart:drgnfire and with Stewart Orchard's highly
+ detailed tmgtest_v1_3 test suite. Although Stewart's tests were
+ designed for Dragons, many apply to the NTSC CoCos, and in fact
+ tuning to those tests improved emulation of coco_cart:drgnfire on
+ NTSC CoCos. There are still many tests in tmgtest_v1_3 that
+ fail and may require work in other components.
**********************************************************************/
@@ -94,21 +111,27 @@ constexpr int LINES_TOP_BORDER = 25;
constexpr int LINES_ACTIVE_VIDEO = 192;
constexpr int LINES_BOTTOM_BORDER = 26;
constexpr int LINES_VERTICAL_RETRACE = 6;
-constexpr int LINES_UNTIL_RETRACE = LINES_TOP_BORDER + LINES_ACTIVE_VIDEO + LINES_BOTTOM_BORDER;
-constexpr int LINES_UNTIL_VBLANK = LINES_UNTIL_RETRACE + LINES_VERTICAL_RETRACE;
+constexpr int LINES_VBLANK = 13;
+
+constexpr int LINES_UNTIL_RETRACE_NTSC = LINES_TOP_BORDER + LINES_ACTIVE_VIDEO + LINES_BOTTOM_BORDER;
+constexpr int LINES_UNTIL_VBLANK_NTSC = LINES_UNTIL_RETRACE_NTSC + LINES_VERTICAL_RETRACE;
+constexpr int LINES_PADDING_TOP_PAL = 25;
+constexpr int LINES_PADDING_BOTTOM_PAL = 25;
+constexpr int LINES_UNTIL_PADDING_BOTTOM_PAL = LINES_PADDING_TOP_PAL + LINES_TOP_BORDER + LINES_ACTIVE_VIDEO +
+ LINES_BOTTOM_BORDER - 2;
+constexpr int LINES_UNTIL_RETRACE_PAL = LINES_PADDING_TOP_PAL + LINES_TOP_BORDER + LINES_ACTIVE_VIDEO +
+ LINES_BOTTOM_BORDER + LINES_PADDING_BOTTOM_PAL;
+constexpr int LINES_UNTIL_VBLANK_PAL = LINES_UNTIL_RETRACE_PAL + LINES_VERTICAL_RETRACE;
constexpr bool USE_HORIZONTAL_CLIP = false;
constexpr int CLOCKS_HSYNC_PERIOD = 228;
-constexpr int CLOCKS_FRONT_PORCH_DURATION = 7;
constexpr int CLOCKS_ACTIVE_VIDEO = 128;
constexpr int CLOCKS_L_OR_R_BORDER = 29;
constexpr int CLOCKS_ACTIVE_VIDEO_AND_BORDERS = CLOCKS_ACTIVE_VIDEO + (2*CLOCKS_L_OR_R_BORDER);
-constexpr int TIMER_HSYNC_OFF_TIME = CLOCKS_ACTIVE_VIDEO_AND_BORDERS + CLOCKS_FRONT_PORCH_DURATION;
-constexpr int TIMER_HSYNC_ON_TIME = TIMER_HSYNC_OFF_TIME + 16;
-
-// FSYNC occurs just after active video, just before right border
-constexpr int TIMER_FSYNC_TIME = CLOCKS_ACTIVE_VIDEO + CLOCKS_L_OR_R_BORDER;
+constexpr int TIMER_HSYNC_OFF_TIME = 212;
+constexpr int TIMER_HSYNC_ON_TIME = 228;
+constexpr int TIMER_FSYNC_TIME = 212;
// These units are the screen device's bitmap pixels. Multiplied by 2 because
// the pixel clock is the mc6847's clock * 2
@@ -150,7 +173,8 @@ const uint32_t mc6847_base_device::s_palette[mc6847_base_device::PALETTE_LENGTH]
//-------------------------------------------------
mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
- const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider, bool supports_partial_body_scanlines)
+ const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider,
+ bool supports_partial_body_scanlines, bool pal)
: device_t(mconfig, type, tag, owner, clock)
, device_video_interface(mconfig, *this)
, m_write_hsync(*this)
@@ -159,10 +183,15 @@ mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device
, m_character_map(fontdata, is_mc6847t1)
, m_tpfs(tpfs)
, m_divider(divider)
+ , m_field_sync_falling_edge_scanline(pal ? field_sync_falling_edge_scanline + LINES_PADDING_TOP_PAL : field_sync_falling_edge_scanline)
, m_supports_partial_body_scanlines(supports_partial_body_scanlines)
+ , m_pal(pal)
+ , m_lines_top_border(pal ? LINES_TOP_BORDER + LINES_PADDING_TOP_PAL : LINES_TOP_BORDER)
+ , m_lines_until_vblank(pal ? LINES_UNTIL_VBLANK_PAL : LINES_UNTIL_VBLANK_NTSC)
+ , m_lines_until_retrace(pal ? LINES_UNTIL_RETRACE_PAL : LINES_UNTIL_RETRACE_NTSC)
{
- // The MC6847 and the GIME apply field sync on different scanlines
- m_field_sync_falling_edge_scanline = field_sync_falling_edge_scanline;
+ // Note: field_sync_falling_edge_scanline is parameterized because the MC6847
+ // and the GIME apply field sync on different scanlines
}
@@ -174,12 +203,10 @@ mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device
void mc6847_friend_device::device_start()
{
/* create the timers */
- m_frame_timer = timer_alloc(FUNC(mc6847_friend_device::new_frame), this);
m_hsync_on_timer = timer_alloc(FUNC(mc6847_friend_device::change_horizontal_sync), this);
m_hsync_off_timer = timer_alloc(FUNC(mc6847_friend_device::change_horizontal_sync), this);
m_fsync_timer = timer_alloc(FUNC(mc6847_friend_device::change_field_sync), this);
- m_frame_timer->adjust(clocks_to_attotime(0), 0, clocks_to_attotime(m_tpfs * CLOCKS_HSYNC_PERIOD * m_divider));
m_hsync_on_timer->adjust(clocks_to_attotime(TIMER_HSYNC_ON_TIME * m_divider), 1, clocks_to_attotime(CLOCKS_HSYNC_PERIOD * m_divider));
m_hsync_off_timer->adjust(clocks_to_attotime(TIMER_HSYNC_OFF_TIME * m_divider), 0, clocks_to_attotime(CLOCKS_HSYNC_PERIOD * m_divider));
@@ -191,7 +218,7 @@ void mc6847_friend_device::device_start()
m_logical_scanline_zone = 0;
m_field_sync = false;
m_horizontal_sync = false;
- set_geometry(LINES_TOP_BORDER, LINES_ACTIVE_VIDEO, false);
+ set_geometry(m_lines_top_border, LINES_ACTIVE_VIDEO, false);
/* save states */
save_item(NAME(m_physical_scanline));
@@ -245,9 +272,10 @@ void mc6847_friend_device::device_post_load()
void mc6847_friend_device::update_field_sync_timer()
{
- // are we expecting field sync?
+ // field sync is expected high from the line before vblanking starts (i.e., from last
+ // vertical retracing line) until but excluding m_field_sync_falling_edge_scanline
bool expected_field_sync = (m_physical_scanline < m_field_sync_falling_edge_scanline)
- || (m_logical_scanline_zone == SCANLINE_ZONE_VBLANK);
+ || (m_physical_scanline >= m_lines_until_vblank - 1);
// do we need to adjust the timer?
if (expected_field_sync != m_field_sync)
@@ -263,19 +291,6 @@ void mc6847_friend_device::update_field_sync_timer()
//-------------------------------------------------
-// new_frame
-//-------------------------------------------------
-
-TIMER_CALLBACK_MEMBER(mc6847_friend_device::new_frame)
-{
- m_physical_scanline = 0;
- m_logical_scanline = 0;
- m_logical_scanline_zone = SCANLINE_ZONE_FRAME_END;
-}
-
-
-
-//-------------------------------------------------
// scanline_zone_string
//-------------------------------------------------
@@ -289,7 +304,6 @@ std::string mc6847_friend_device::scanline_zone_string(scanline_zone zone) const
case SCANLINE_ZONE_BOTTOM_BORDER: result = "SCANLINE_ZONE_BOTTOM_BORDER"; break;
case SCANLINE_ZONE_RETRACE: result = "SCANLINE_ZONE_RETRACE"; break;
case SCANLINE_ZONE_VBLANK: result = "SCANLINE_ZONE_VBLANK"; break;
- case SCANLINE_ZONE_FRAME_END: result = "SCANLINE_ZONE_FRAME_END"; break;
default:
fatalerror("Should not get here\n");
}
@@ -333,7 +347,6 @@ TIMER_CALLBACK_MEMBER(mc6847_friend_device::change_horizontal_sync)
case SCANLINE_ZONE_RETRACE:
case SCANLINE_ZONE_VBLANK:
- case SCANLINE_ZONE_FRAME_END:
// do nothing
break;
}
@@ -355,8 +368,12 @@ TIMER_CALLBACK_MEMBER(mc6847_friend_device::change_horizontal_sync)
// log if apprpriate
LOGMASKED(LOG_HSYNC, "%s: change_horizontal_sync(): line=%d, (vpos,hpos)=(%d,%d), m_physical_scanline=%d\n", describe_context(), line ? 1 : 0, screen().vpos(), screen().hpos(), m_physical_scanline);
- // invoke callback
- m_write_hsync(line);
+ // invoke callback (to issue interrupt) if this isn't a PAL padding line
+ // TODO: Apparently HS is inhibited during PAL padding on Dragon 64, but
+ // not Dragon 32. I do not know the behavior on other PAL 6847 machines.
+ // For now, inhibiting for all PAL machines
+ if (!is_pal_padding_line(m_physical_scanline))
+ m_write_hsync(line);
// call virtual function
horizontal_sync_changed(m_horizontal_sync);
@@ -402,19 +419,22 @@ inline void mc6847_friend_device::next_scanline()
m_partial_scanline_clocks = 0;
/* check for movement into the next "zone" */
- if (m_logical_scanline_zone == SCANLINE_ZONE_FRAME_END)
+ if ((m_logical_scanline_zone == SCANLINE_ZONE_VBLANK) &&
+ (m_logical_scanline >= LINES_VBLANK))
{
- /* we're now in the top border */
+ /* new frame, starts at top border */
+ m_physical_scanline = 0;
m_logical_scanline = 0;
m_logical_scanline_zone = SCANLINE_ZONE_TOP_BORDER;
+ new_frame();
}
- else if ((m_logical_scanline_zone < SCANLINE_ZONE_VBLANK) && (m_physical_scanline >= LINES_UNTIL_VBLANK))
+ else if ((m_logical_scanline_zone < SCANLINE_ZONE_VBLANK) && (m_physical_scanline >= m_lines_until_vblank))
{
/* we're now into vblank */
m_logical_scanline = 0;
m_logical_scanline_zone = SCANLINE_ZONE_VBLANK;
}
- else if ((m_logical_scanline_zone < SCANLINE_ZONE_RETRACE) && (m_physical_scanline >= LINES_UNTIL_RETRACE))
+ else if ((m_logical_scanline_zone < SCANLINE_ZONE_RETRACE) && (m_physical_scanline >= m_lines_until_retrace))
{
/* we're now into retrace */
m_logical_scanline = 0;
@@ -434,17 +454,60 @@ inline void mc6847_friend_device::next_scanline()
enter_bottom_border();
}
- LOGMASKED(\
- LOG_NEXTLINE, \
- "mc6847_friend_device::next_scanline(): (vpos,hpos)=(%d,%d), m_physical_scanline='%d', m_logical_scanline_zone='%s', m_logical_scanline='%d'\n", \
- screen().vpos(), \
- screen().hpos(), \
- m_physical_scanline, \
- scanline_zone_string((scanline_zone)m_logical_scanline_zone), \
+ LOGMASKED(
+ LOG_NEXTLINE,
+ "mc6847_friend_device::next_scanline(): (vpos,hpos)=(%d,%d), m_physical_scanline='%d', m_logical_scanline_zone='%s', m_logical_scanline='%d'\n",
+ screen().vpos(),
+ screen().hpos(),
+ m_physical_scanline,
+ scanline_zone_string((scanline_zone)m_logical_scanline_zone),
m_logical_scanline);
}
+//-------------------------------------------------
+// is_top_pal_padding_line
+//-------------------------------------------------
+
+inline bool mc6847_friend_device::is_top_pal_padding_line(int scanline) const
+{
+ // PAL adds 25 padding scanlines before top border
+ return m_pal && scanline < LINES_PADDING_TOP_PAL;
+}
+
+
+//-------------------------------------------------
+// is_bottom_pal_padding_line
+//-------------------------------------------------
+
+inline bool mc6847_friend_device::is_bottom_pal_padding_line(int scanline) const
+{
+ // PAL adds 25 padding scanlines nested INSIDE the bottom border
+ // (just a couple lines up from the end of the bottom border).
+ return m_pal &&
+ LINES_UNTIL_PADDING_BOTTOM_PAL <= scanline &&
+ scanline < LINES_UNTIL_PADDING_BOTTOM_PAL + LINES_PADDING_BOTTOM_PAL;
+}
+
+
+//-------------------------------------------------
+// is_pal_padding_line
+//-------------------------------------------------
+
+inline bool mc6847_friend_device::is_pal_padding_line(int scanline) const
+{
+ return is_top_pal_padding_line(scanline) || is_bottom_pal_padding_line(scanline);
+}
+
+
+//-------------------------------------------------
+// new_frame
+//-------------------------------------------------
+
+void mc6847_friend_device::new_frame()
+{
+}
+
//-------------------------------------------------
// horizontal_sync_changed
@@ -549,8 +612,17 @@ std::string mc6847_friend_device::describe_context() const
// ctor
//-------------------------------------------------
-mc6847_base_device::mc6847_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs) :
- mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, LINES_TOP_BORDER + LINES_ACTIVE_VIDEO - 1, 1, true),
+mc6847_base_device::mc6847_base_device(
+ const machine_config &mconfig,
+ device_type type,
+ const char *tag,
+ device_t *owner,
+ uint32_t clock,
+ const uint8_t *fontdata,
+ double tpfs,
+ bool pal) :
+ mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL),
+ tpfs, LINES_TOP_BORDER + LINES_ACTIVE_VIDEO - 1, 1, true, pal),
m_input_cb(*this, 0),
m_black_and_white(false),
m_fixed_mode(0),
@@ -600,18 +672,14 @@ void mc6847_base_device::device_config_complete()
// Multiplying the 6847's clock by 2 produces a pixel clock that allows
// 256 pixels of active video area per line, with apparently no roundoff
// error or drift.
- //
- // Note: This math is valid for NTSC. If / when PAL is implemented, m_tpfs
- // can be used to determine if this 6847 is PAL, and a different set_raw
- // call can be made if helpful.
screen().set_raw(
- (uint32_t)(clock() * 2),
- 456, // htotal
- 0, // hbend
- BMP_L_OR_R_BORDER * 2 + BMP_ACTIVE_VIDEO, // hbstart
- m_tpfs, // vtotal
- 0, // vbend
- LINES_UNTIL_RETRACE); // vbstart
+ uint32_t(clock() * 2),
+ 456, // htotal
+ 0, // hbend
+ BMP_L_OR_R_BORDER * 2 + BMP_ACTIVE_VIDEO, // hbstart
+ m_tpfs, // vtotal
+ 0, // vbend
+ m_lines_until_retrace); // vbstart
}
if (!screen().has_screen_update())
@@ -882,10 +950,9 @@ inline mc6847_base_device::pixel_t mc6847_base_device::border_value(uint8_t mode
uint32_t mc6847_base_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
+ const bool is_mc6847t1 = (type() == MC6847T1_NTSC) || (type() == MC6847T1_PAL);
int base_x = BMP_L_OR_R_BORDER;
- int base_y = LINES_TOP_BORDER;
- int x, x2, y, width;
- bool is_mc6847t1 = (type() == MC6847T1_NTSC) || (type() == MC6847T1_PAL);
+ int base_y = m_lines_top_border;
int min_x = USE_HORIZONTAL_CLIP ? cliprect.min_x : 0;
int max_x = USE_HORIZONTAL_CLIP ? cliprect.max_x : (base_x * 2 + BMP_ACTIVE_VIDEO - 1);
int min_y = cliprect.min_y;
@@ -897,42 +964,47 @@ uint32_t mc6847_base_device::screen_update(screen_device &screen, bitmap_rgb32 &
return UPDATE_HAS_NOT_CHANGED;
/* top border */
- for (y = min_y; y < base_y; y++)
+ for (int y = min_y; y < base_y; y++)
{
- for (x = min_x; x <= max_x; x++)
+ // PAL padding is always black, even when border isn't
+ const pixel_t color = is_top_pal_padding_line(y)
+ ? palette[8]
+ : border_value(m_data[0].m_mode[0], palette, is_mc6847t1);
+
+ for (int x = min_x; x <= max_x; x++)
{
- *bitmap_addr(bitmap, y, x) = border_value(m_data[0].m_mode[0], palette, is_mc6847t1);
+ *bitmap_addr(bitmap, y, x) = color;
}
}
- for (y = std::max(0, min_y - base_y); y < std::min(LINES_ACTIVE_VIDEO, max_y - base_y); y++)
+ for (int y = std::max(0, min_y - base_y); y < std::min(LINES_ACTIVE_VIDEO, max_y - base_y); y++)
{
/* left border */
- for (x = min_x; x < base_x; x++)
+ for (int x = min_x; x < base_x; x++)
{
*bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[0], palette, is_mc6847t1);
}
/* body */
- x = 0;
- width = m_data[y].m_sample_count;
+ const int width = m_data[y].m_sample_count;
pixel_t *RESTRICT pixels = bitmap_addr(bitmap, base_y + y, base_x);
- while(x < width)
+ for (int x; x < width; )
{
/* determine how many bytes exist for which the mode is identical */
+ int x2;
for (x2 = x + 1; (x2 < width) && (m_data[y].m_mode[x] == m_data[y].m_mode[x2]); x2++)
;
/* emit the samples */
pixels += emit_mc6847_samples<1>(
- m_data[y].m_mode[x],
- &m_data[y].m_data[x],
- x2 - x,
- pixels,
- m_palette,
- m_charrom_cb,
- x,
- y);
+ m_data[y].m_mode[x],
+ &m_data[y].m_data[x],
+ x2 - x,
+ pixels,
+ m_palette,
+ m_charrom_cb,
+ x,
+ y);
/* update x */
x = x2;
@@ -940,27 +1012,39 @@ uint32_t mc6847_base_device::screen_update(screen_device &screen, bitmap_rgb32 &
/* right border */
if (width)
- for (x = base_x + BMP_ACTIVE_VIDEO; x <= max_x; x++)
+ for (int x = base_x + BMP_ACTIVE_VIDEO; x <= max_x; x++)
*bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[width - 1], palette, is_mc6847t1);
/* artifacting */
- if( m_artifacter.get_pal_artifacting() )
+ if (m_artifacter.get_pal_artifacting())
{
- if( y % 2)
+ if (y % 2)
m_artifacter.process_artifacts_pal<1>(bitmap, y - 1, base_x, base_y, m_data[y].m_mode[0], palette);
}
else
+ {
m_artifacter.process_artifacts<1>(bitmap_addr(bitmap, y + base_y, base_x), m_data[y].m_mode[0], palette);
-
+ }
}
- width = m_data[LINES_ACTIVE_VIDEO-1].m_sample_count;
+ const int width = m_data[LINES_ACTIVE_VIDEO-1].m_sample_count;
/* bottom border */
if (width)
- for (y = base_y + LINES_ACTIVE_VIDEO - 1; y <= max_y; y++)
- for (x = min_x; x <= max_x; x++)
- *bitmap_addr(bitmap, y, x) = border_value(m_data[LINES_ACTIVE_VIDEO - 1].m_mode[width - 1], palette, is_mc6847t1);
+ {
+ for (int y = base_y + LINES_ACTIVE_VIDEO; y <= max_y; y++)
+ {
+ // PAL padding is always black, even when border isn't
+ pixel_t color = is_bottom_pal_padding_line(y)
+ ? palette[8]
+ : border_value(m_data[LINES_ACTIVE_VIDEO - 1].m_mode[width - 1], palette, is_mc6847t1);
+
+ for (int x = min_x; x <= max_x; x++)
+ {
+ *bitmap_addr(bitmap, y, x) = color;
+ }
+ }
+ }
return 0;
}
@@ -1682,7 +1766,7 @@ DEFINE_DEVICE_TYPE(M5C6847P1, m5c6847p1_device, "m5c6847p1", "Mitsub
//-------------------------------------------------
mc6847_ntsc_device::mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847_NTSC, tag, owner, clock, vdg_fontdata8x12, 262.0)
+ : mc6847_base_device(mconfig, MC6847_NTSC, tag, owner, clock, vdg_fontdata8x12, 262.0, false)
{
}
@@ -1693,7 +1777,7 @@ mc6847_ntsc_device::mc6847_ntsc_device(const machine_config &mconfig, const char
//-------------------------------------------------
mc6847_pal_device::mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847_PAL, tag, owner, clock, vdg_fontdata8x12, 313.0)
+ : mc6847_base_device(mconfig, MC6847_PAL, tag, owner, clock, vdg_fontdata8x12, 312.0, true)
{
m_artifacter.set_pal_artifacting(true);
}
@@ -1705,7 +1789,7 @@ mc6847_pal_device::mc6847_pal_device(const machine_config &mconfig, const char *
//-------------------------------------------------
mc6847y_ntsc_device::mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847Y_NTSC, tag, owner, clock, vdg_fontdata8x12, 262.5)
+ : mc6847_base_device(mconfig, MC6847Y_NTSC, tag, owner, clock, vdg_fontdata8x12, 262.5, false)
{
}
@@ -1716,7 +1800,7 @@ mc6847y_ntsc_device::mc6847y_ntsc_device(const machine_config &mconfig, const ch
//-------------------------------------------------
mc6847y_pal_device::mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847Y_PAL, tag, owner, clock, vdg_fontdata8x12, 313.0)
+ : mc6847_base_device(mconfig, MC6847Y_PAL, tag, owner, clock, vdg_fontdata8x12, 312.0, true)
{
m_artifacter.set_pal_artifacting(true);
}
@@ -1728,7 +1812,7 @@ mc6847y_pal_device::mc6847y_pal_device(const machine_config &mconfig, const char
//-------------------------------------------------
mc6847t1_ntsc_device::mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847T1_NTSC, tag, owner, clock, vdg_t1_fontdata8x12, 262.0)
+ : mc6847_base_device(mconfig, MC6847T1_NTSC, tag, owner, clock, vdg_t1_fontdata8x12, 262.0, false)
{
}
@@ -1739,7 +1823,7 @@ mc6847t1_ntsc_device::mc6847t1_ntsc_device(const machine_config &mconfig, const
//-------------------------------------------------
mc6847t1_pal_device::mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, MC6847T1_PAL, tag, owner, clock, vdg_t1_fontdata8x12, 313.0)
+ : mc6847_base_device(mconfig, MC6847T1_PAL, tag, owner, clock, vdg_t1_fontdata8x12, 312.0, true)
{
m_artifacter.set_pal_artifacting(true);
}
@@ -1751,7 +1835,7 @@ mc6847t1_pal_device::mc6847t1_pal_device(const machine_config &mconfig, const ch
//-------------------------------------------------
s68047_device::s68047_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, S68047, tag, owner, clock, s68047_fontdata8x12, 262.0)
+ : mc6847_base_device(mconfig, S68047, tag, owner, clock, s68047_fontdata8x12, 262.0, false)
{
}
@@ -1800,6 +1884,6 @@ const uint32_t s68047_device::s_s68047_hack_palette[16] =
//-------------------------------------------------
m5c6847p1_device::m5c6847p1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mc6847_base_device(mconfig, M5C6847P1, tag, owner, clock, vdg_fontdata8x12, 262.5)
+ : mc6847_base_device(mconfig, M5C6847P1, tag, owner, clock, vdg_fontdata8x12, 262.5, false)
{
}
diff --git a/src/devices/video/mc6847.h b/src/devices/video/mc6847.h
index 06cfacc4f57..8db7e58c881 100644
--- a/src/devices/video/mc6847.h
+++ b/src/devices/video/mc6847.h
@@ -58,7 +58,8 @@ public:
protected:
mc6847_friend_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
- const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider, bool supports_partial_body_scanlines);
+ const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider,
+ bool supports_partial_body_scanlines, bool pal);
// fonts
static const uint8_t vdg_t1_fontdata8x12[];
@@ -271,7 +272,7 @@ protected:
virtual void device_post_load() override;
// other overridables
- virtual TIMER_CALLBACK_MEMBER(new_frame);
+ virtual void new_frame();
virtual TIMER_CALLBACK_MEMBER(horizontal_sync_changed);
virtual void field_sync_changed(bool line);
virtual void enter_bottom_border();
@@ -455,11 +456,9 @@ private:
SCANLINE_ZONE_BOTTOM_BORDER,
SCANLINE_ZONE_RETRACE,
SCANLINE_ZONE_VBLANK,
- SCANLINE_ZONE_FRAME_END
};
// timers
- emu_timer *m_frame_timer;
emu_timer *m_hsync_on_timer;
emu_timer *m_hsync_off_timer;
emu_timer *m_fsync_timer;
@@ -470,7 +469,7 @@ protected:
private:
// incidentals
const int m_divider;
- int m_field_sync_falling_edge_scanline;
+ const int m_field_sync_falling_edge_scanline;
bool m_wide;
bool m_video_changed;
uint16_t m_top_border_scanlines;
@@ -478,6 +477,13 @@ private:
bool m_recording_scanline;
const bool m_supports_partial_body_scanlines;
+protected:
+ const bool m_pal;
+ const uint16_t m_lines_top_border;
+ const uint16_t m_lines_until_vblank;
+ const uint16_t m_lines_until_retrace;
+
+private:
// video state
uint16_t m_physical_scanline;
uint16_t m_logical_scanline;
@@ -495,6 +501,11 @@ private:
// debugging
std::string scanline_zone_string(scanline_zone zone) const;
+
+protected:
+ bool is_top_pal_padding_line(int scanline) const;
+ bool is_bottom_pal_padding_line(int scanline) const;
+ bool is_pal_padding_line(int scanline) const;
};
// actual base class for MC6847 family of devices
@@ -522,7 +533,7 @@ public:
void inv_w(int state) { change_mode(MODE_INV, state); }
protected:
- mc6847_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs);
+ mc6847_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs, bool pal);
// device-level overrides
virtual void device_config_complete() override;
diff --git a/src/mame/trs/coco3.cpp b/src/mame/trs/coco3.cpp
index 3cc3e69dc48..ce812d70634 100644
--- a/src/mame/trs/coco3.cpp
+++ b/src/mame/trs/coco3.cpp
@@ -307,7 +307,7 @@ void coco3_state::coco3(machine_config &config)
// monitor
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640-1, 263, 1, 241-1);
+ m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640-1, 262, 1, 241-1);
m_screen->set_screen_update(FUNC(coco3_state::screen_update));
// internal ram
diff --git a/src/mame/trs/dragon.cpp b/src/mame/trs/dragon.cpp
index ad6fed3932a..e76baee1502 100644
--- a/src/mame/trs/dragon.cpp
+++ b/src/mame/trs/dragon.cpp
@@ -516,7 +516,7 @@ void dragon_state::dragon_base(machine_config &config)
// video hardware
SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER);
- MC6847_PAL(config, m_vdg, 4.433619_MHz_XTAL);
+ MC6847_PAL(config, m_vdg, 14.218_MHz_XTAL / 4);
m_vdg->set_screen(SCREEN_TAG);
m_vdg->hsync_wr_callback().set(FUNC(dragon_state::horizontal_sync));
m_vdg->fsync_wr_callback().set(FUNC(dragon_state::field_sync));
diff --git a/src/mame/trs/gime.cpp b/src/mame/trs/gime.cpp
index 967d26643d3..24a59e24dce 100644
--- a/src/mame/trs/gime.cpp
+++ b/src/mame/trs/gime.cpp
@@ -138,8 +138,8 @@
// ctor
//-------------------------------------------------
-gime_device::gime_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata)
- : mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, true, 263, 25+192+26+3, 8, false)
+gime_device::gime_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, bool pal)
+ : mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, true, 262, 25+192+26+1, 8, false, pal)
, sam6883_friend_device_interface(mconfig, *this, 8)
, m_write_irq(*this)
, m_write_firq(*this)
@@ -1231,10 +1231,10 @@ inline offs_t gime_device::get_video_base()
// new_frame
//-------------------------------------------------
-TIMER_CALLBACK_MEMBER(gime_device::new_frame)
+void gime_device::new_frame()
{
/* call inherited function */
- super::new_frame(param);
+ super::new_frame();
/* latch in legacy video value */
bool legacy_video_changed = update_value(&m_legacy_video, m_gime_registers[0] & 0x80 ? true : false);
@@ -2210,10 +2210,10 @@ DEFINE_DEVICE_TYPE(GIME_NTSC, gime_ntsc_device, "gime_ntsc", "TCC1014 (VC2645QC)
DEFINE_DEVICE_TYPE(GIME_PAL, gime_pal_device, "gime_pal", "TCC1014 (VC2645QC) GIME (PAL)")
gime_ntsc_device::gime_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gime_device(mconfig, GIME_NTSC, tag, owner, clock, lowres_font) { }
+ : gime_device(mconfig, GIME_NTSC, tag, owner, clock, lowres_font, false) { }
gime_pal_device::gime_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gime_device(mconfig, GIME_PAL, tag, owner, clock, lowres_font) { }
+ : gime_device(mconfig, GIME_PAL, tag, owner, clock, lowres_font, true) { }
template class device_finder<gime_device, false>;
template class device_finder<gime_device, true>;
diff --git a/src/mame/trs/gime.h b/src/mame/trs/gime.h
index ed255d28f56..886f219c1cb 100644
--- a/src/mame/trs/gime.h
+++ b/src/mame/trs/gime.h
@@ -61,7 +61,7 @@ public:
void set_il2(bool value) { set_interrupt_value(INTERRUPT_EI2, value); }
protected:
- gime_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata);
+ gime_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, bool pal);
// device-level overrides
virtual void device_start() override;
@@ -71,7 +71,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// other overrides
- virtual TIMER_CALLBACK_MEMBER(new_frame) override;
+ virtual void new_frame() override;
virtual TIMER_CALLBACK_MEMBER(horizontal_sync_changed) override;
virtual void enter_bottom_border() override;
virtual void record_border_scanline(uint16_t physical_scanline) override;