From b0c924a959a17f68a6dafd06bf17bb4f1f44e0e1 Mon Sep 17 00:00:00 2001 From: dave-br Date: Fri, 22 Dec 2023 06:23:13 -0800 Subject: video/mc6847.cpp: Fixed synchronization on Dragon (PAL) machines. (#11743) --- src/devices/video/mc6847.cpp | 272 ++++++++++++++++++++++++++++--------------- src/devices/video/mc6847.h | 23 +++- src/mame/trs/coco3.cpp | 2 +- src/mame/trs/dragon.cpp | 2 +- src/mame/trs/gime.cpp | 12 +- src/mame/trs/gime.h | 4 +- 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) @@ -262,19 +290,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; template class device_finder; 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; -- cgit v1.2.3