diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/devices/video/crtc_ega.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/devices/video/crtc_ega.cpp')
-rw-r--r-- | src/devices/video/crtc_ega.cpp | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/src/devices/video/crtc_ega.cpp b/src/devices/video/crtc_ega.cpp new file mode 100644 index 00000000000..102df087008 --- /dev/null +++ b/src/devices/video/crtc_ega.cpp @@ -0,0 +1,728 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/********************************************************************** + + IBM EGA CRT Controller emulation + + This controller is very loosely based on the mc6845. + +**********************************************************************/ + +#include "emu.h" +#include "crtc_ega.h" + + +#define LOG (1) + + +const device_type CRTC_EGA = &device_creator<crtc_ega_device>; + + +crtc_ega_device::crtc_ega_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, CRTC_EGA, "crtc_EGA", tag, owner, clock, "crtc_ega", __FILE__), + device_video_interface(mconfig, *this, false), + m_res_out_de_cb(*this), + m_res_out_hsync_cb(*this), + m_res_out_vsync_cb(*this), + m_res_out_vblank_cb(*this), + m_hpixels_per_column(0) +{ +} + + +void crtc_ega_device::device_post_load() +{ + recompute_parameters(true); +} + + +WRITE8_MEMBER( crtc_ega_device::address_w ) +{ + m_register_address_latch = data & 0x1f; +} + + +READ8_MEMBER( crtc_ega_device::register_r ) +{ + UINT8 ret = 0; + + switch (m_register_address_latch) + { + case 0x0c: ret = (m_disp_start_addr >> 8) & 0xff; break; + case 0x0d: ret = (m_disp_start_addr >> 0) & 0xff; break; + case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break; + case 0x0f: ret = (m_cursor_addr >> 0) & 0xff; break; + case 0x10: ret = (m_light_pen_addr >> 8) & 0xff; m_light_pen_latched = FALSE; break; + case 0x11: ret = (m_light_pen_addr >> 0) & 0xff; m_light_pen_latched = FALSE; break; + + /* all other registers are write only and return 0 */ + default: break; + } + + return ret; +} + + +WRITE8_MEMBER( crtc_ega_device::register_w ) +{ + if (LOG) logerror("%s CRTC_EGA: reg 0x%02x = 0x%02x\n", machine().describe_context(), m_register_address_latch, data); + + switch (m_register_address_latch) + { + case 0x00: m_horiz_char_total = data & 0xff; break; + case 0x01: m_horiz_disp = data & 0xff; break; + case 0x02: m_horiz_blank_start = data & 0xff; break; + case 0x03: m_horiz_blank_end = ((data & 0x1f) << 0) | (m_horiz_blank_end & 0x20); + m_de_skew = ((data & 0x60) >> 5); + m_ena_vert_access = data & 0x80; + break; + case 0x04: m_horiz_retr_start = data & 0xff; break; + case 0x05: m_horiz_retr_end = data & 0x1f; + m_horiz_retr_skew = ((data & 0x60) >> 5); + m_horiz_blank_end = ((data & 0x80) >> 2) | (m_horiz_blank_end & 0x1f); + break; + case 0x06: m_vert_total = ((data & 0xff) << 0) | (m_vert_total & 0x0300); break; + case 0x07: m_vert_total = ((data & 0x01) << 8) | (m_vert_total & 0x02ff); + m_vert_disp_end = ((data & 0x02) << 7) | (m_vert_disp_end & 0x02ff); + m_vert_retr_start = ((data & 0x04) << 6) | (m_vert_retr_start & 0x02ff); + m_vert_blank_start = ((data & 0x08) << 5) | (m_vert_blank_start & 0x02ff); + m_line_compare = ((data & 0x10) << 4) | (m_line_compare & 0x02ff); + m_vert_total = ((data & 0x20) << 4) | (m_vert_total & 0x01ff); + m_vert_disp_end = ((data & 0x40) << 3) | (m_vert_disp_end & 0x1ff); + m_vert_retr_start = ((data & 0x80) << 2) | (m_vert_retr_start & 0x01ff); + break; + case 0x08: m_preset_row_scan = data & 0x1f; + m_byte_panning = ((data & 0x60) >> 5); + break; + case 0x09: m_max_ras_addr = data & 0x1f; + m_vert_blank_start = ((data & 0x20) << 4) | (m_vert_blank_start & 0x01ff); + m_line_compare = ((data & 0x40) << 3) | (m_line_compare & 0x01ff); + m_scan_doubling = data & 0x80; + break; + case 0x0a: m_cursor_start_ras = data & 0x1f; + m_cursor_disable = data & 0x20; + break; + case 0x0b: m_cursor_end_ras = data & 0x1f; + m_cursor_skew = ((data & 0x60) >> 5); + break; + case 0x0c: m_disp_start_addr = ((data & 0xff) << 8) | (m_disp_start_addr & 0x00ff); break; + case 0x0d: m_disp_start_addr = ((data & 0xff) << 0) | (m_disp_start_addr & 0xff00); break; + case 0x0e: m_cursor_addr = ((data & 0xff) << 8) | (m_cursor_addr & 0x00ff); break; + case 0x0f: m_cursor_addr = ((data & 0xff) << 0) | (m_cursor_addr & 0xff00); break; + case 0x10: m_vert_retr_start = ((data & 0xff) << 0) | (m_vert_retr_start & 0x0300); break; + case 0x11: m_vert_retr_end = data & 0x0f; + m_bandwidth = data & 0x40; + m_protect = data & 0x80; + break; + case 0x12: m_vert_disp_end = ((data & 0xff) << 0) | (m_vert_disp_end & 0x0300); break; + case 0x13: m_offset = data & 0xff; break; + case 0x14: m_underline_loc = data & 0x7f; break; + case 0x15: m_vert_blank_start = ((data & 0xff) << 0) | (m_vert_blank_start & 0x0300); break; + case 0x16: m_vert_blank_end = data & 0x7f; break; + case 0x17: m_mode_control = data & 0xff; break; + case 0x18: m_line_compare = ((data & 0xff) << 0) | (m_line_compare & 0x0300); break; + default: break; + } + + recompute_parameters(false); +} + + +void crtc_ega_device::recompute_parameters(bool postload) +{ + UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; + + /* compute the screen sizes */ + UINT16 horiz_pix_total = (m_horiz_char_total + 2) * m_hpixels_per_column; + UINT16 vert_pix_total = m_vert_total + 1; + + /* determine the visible area, avoid division by 0 */ + UINT16 max_visible_x = ( m_horiz_disp + 1 ) * m_hpixels_per_column - 1; + UINT16 max_visible_y = m_vert_disp_end; + + /* determine the syncing positions */ + int horiz_sync_char_width = ( m_horiz_retr_end + 1 ) - ( m_horiz_retr_start & 0x1f ); + int vert_sync_pix_width = m_vert_retr_end - ( m_vert_retr_start & 0x0f ); + + if (horiz_sync_char_width <= 0) + horiz_sync_char_width += 0x10; + + if (vert_sync_pix_width <= 0) + vert_sync_pix_width += 0x10; + + hsync_on_pos = m_horiz_retr_start * m_hpixels_per_column; + hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * m_hpixels_per_column); + vsync_on_pos = m_vert_retr_start; /* + 1 ?? */ + vsync_off_pos = vsync_on_pos + vert_sync_pix_width; + + if (hsync_off_pos > horiz_pix_total) + hsync_off_pos = horiz_pix_total; + + if (vsync_off_pos > vert_pix_total) + vsync_off_pos = vert_pix_total; + + if ( vsync_on_pos >= vsync_off_pos ) + { + vsync_on_pos = vsync_off_pos - 2; + } + + /* update only if screen parameters changed, unless we are coming here after loading the saved state */ + if (postload || + (horiz_pix_total != m_horiz_pix_total) || (vert_pix_total != m_vert_pix_total) || + (max_visible_x != m_max_visible_x) || (max_visible_y != m_max_visible_y) || + (hsync_on_pos != m_hsync_on_pos) || (vsync_on_pos != m_vsync_on_pos) || + (hsync_off_pos != m_hsync_off_pos) || (vsync_off_pos != m_vsync_off_pos)) + { + /* update the screen if we have valid data */ + if ((horiz_pix_total > 0) && (max_visible_x < horiz_pix_total) && + (vert_pix_total > 0) && (max_visible_y < vert_pix_total) && + (hsync_on_pos <= horiz_pix_total) && (vsync_on_pos <= vert_pix_total) && + (hsync_on_pos != hsync_off_pos)) + { + attoseconds_t refresh = HZ_TO_ATTOSECONDS(m_clock) * (m_horiz_char_total + 2) * vert_pix_total; + + rectangle visarea(0, max_visible_x, 0, max_visible_y); + + if (LOG) logerror("CRTC_EGA config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x Freq: %ffps\n", + horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); + + if ( m_screen != NULL ) + m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); + + m_has_valid_parameters = true; + } + else + { + m_has_valid_parameters = false; + if (LOG) logerror("CRTC_EGA bad config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x\n", + horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1); + + } + + m_horiz_pix_total = horiz_pix_total; + m_vert_pix_total = vert_pix_total; + m_max_visible_x = max_visible_x; + m_max_visible_y = max_visible_y; + m_hsync_on_pos = hsync_on_pos; + m_hsync_off_pos = hsync_off_pos; + m_vsync_on_pos = vsync_on_pos; + m_vsync_off_pos = vsync_off_pos; + } +} + + +void crtc_ega_device::update_counters() +{ + m_character_counter = m_line_timer->elapsed().as_ticks( m_clock ); + + if ( m_hsync_off_timer->enabled() ) + { + m_hsync_width_counter = m_hsync_off_timer->elapsed().as_ticks( m_clock ); + } +} + + +void crtc_ega_device::set_de(int state) +{ + if (m_de != state) + { + m_de = state; + + if (!m_res_out_de_cb.isnull()) + m_res_out_de_cb(m_de); + } +} + + +void crtc_ega_device::set_hsync(int state) +{ + if (m_hsync != state) + { + m_hsync = state; + + if (!m_res_out_hsync_cb.isnull()) + m_res_out_hsync_cb(m_hsync); + } +} + + +void crtc_ega_device::set_vsync(int state) +{ + if (m_vsync != state) + { + m_vsync = state; + + if (!m_res_out_vsync_cb.isnull()) + m_res_out_vsync_cb(m_vsync); + } +} + + +void crtc_ega_device::set_vblank(int state) +{ + if (m_vblank != state) + { + m_vblank = state; + + if (!m_res_out_vblank_cb.isnull()) + m_res_out_vblank_cb(m_vblank); + } +} + + +void crtc_ega_device::set_cur(int state) +{ + if (m_cur != state) + { + m_cur = state; + +// if (!m_res_out_cur_cb.isnull()) +// m_res_out_cur_cb(m_cur); + } +} + + +void crtc_ega_device::handle_line_timer() +{ + int new_vsync = m_vsync; + + m_character_counter = 0; + m_cursor_x = -1; + + /* Check if VSYNC is active */ + if ( m_vsync_ff ) + { + m_vsync_width_counter = ( m_vsync_width_counter + 1 ) & 0x0F; + + /* Check if we've reached end of VSYNC */ + if ( m_vsync_width_counter == m_vert_retr_end ) + { + m_vsync_ff = 0; + + new_vsync = FALSE; + } + } + + if ( m_raster_counter == m_max_ras_addr ) + { + m_raster_counter = 0; + m_line_address = ( m_line_address + m_horiz_disp + 1 ) & 0xffff; + } + else + { + m_raster_counter = ( m_raster_counter + 1 ) & 0x1F; + } + + m_line_counter = ( m_line_counter + 1 ) & 0x3ff; + + /* Check if we've reached the end of active display */ + if ( m_line_counter == m_vert_disp_end ) + { + m_line_enable_ff = false; + } + + /* Check if VSYNC should be enabled */ + if ( m_line_counter == m_vert_retr_start ) + { + m_vsync_width_counter = 0; + m_vsync_ff = 1; + + new_vsync = TRUE; + } + + /* Check if we have reached the end of the vertical area */ + if ( m_line_counter == m_vert_total ) + { + m_line_counter = 0; + m_line_address = m_disp_start_addr; + m_line_enable_ff = true; + set_vblank( FALSE ); + /* also update the cursor state now */ + update_cursor_state(); + + if (m_screen != NULL) + m_screen->reset_origin(); + } + + if ( m_line_enable_ff ) + { + /* Schedule DE off signal change */ + m_de_off_timer->adjust(attotime::from_ticks( m_horiz_disp + 1, m_clock )); + + /* Is cursor visible on this line? */ + if ( m_cursor_state && + (m_raster_counter >= (m_cursor_start_ras & 0x1f)) && + (m_raster_counter <= m_cursor_end_ras) && + (m_cursor_addr >= m_line_address) && + (m_cursor_addr < (m_line_address + m_horiz_disp + 1)) ) + { + m_cursor_x = m_cursor_addr - m_line_address; + + /* Schedule CURSOR ON signal */ + m_cur_on_timer->adjust( attotime::from_ticks( m_cursor_x, m_clock ) ); + } + } + + /* Schedule HSYNC on signal */ + m_hsync_on_timer->adjust( attotime::from_ticks( m_horiz_blank_start, m_clock ) ); + + /* Set VBlank signal */ + if ( m_line_counter == m_vert_disp_end + 1 ) + { + set_vblank( TRUE ); + } + + /* Schedule our next callback */ + m_line_timer->adjust( attotime::from_ticks( m_horiz_char_total + 2, m_clock ) ); + + /* Set VSYNC and DE signals */ + set_vsync( new_vsync ); + set_de( m_line_enable_ff ? TRUE : FALSE ); +} + + +void crtc_ega_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_LINE: + handle_line_timer(); + break; + + case TIMER_DE_OFF: + set_de( FALSE ); + break; + + case TIMER_CUR_ON: + set_cur( TRUE ); + + /* Schedule CURSOR off signal */ + m_cur_off_timer->adjust( attotime::from_ticks( 1, m_clock ) ); + break; + + case TIMER_CUR_OFF: + set_cur( FALSE ); + break; + + case TIMER_HSYNC_ON: + { + INT8 hsync_width = ( 0x20 | m_horiz_blank_end ) - ( m_horiz_blank_start & 0x1f ); + + if ( hsync_width <= 0 ) + { + hsync_width += 0x20; + } + + m_hsync_width_counter = 0; + set_hsync( TRUE ); + + /* Schedule HSYNC off signal */ + m_hsync_off_timer->adjust( attotime::from_ticks( hsync_width, m_clock ) ); + } + break; + + case TIMER_HSYNC_OFF: + set_hsync( FALSE ); + break; + + case TIMER_LIGHT_PEN_LATCH: + m_light_pen_addr = get_ma(); + m_light_pen_latched = true; + break; + } +} + + +UINT16 crtc_ega_device::get_ma() +{ + update_counters(); + + return m_line_address + m_character_counter; +} + + +UINT8 crtc_ega_device::get_ra() +{ + return m_raster_counter; +} + + +void crtc_ega_device::assert_light_pen_input() +{ + /* compute the pixel coordinate of the NEXT character -- this is when the light pen latches */ + /* set the timer that will latch the display address into the light pen registers */ + m_light_pen_latch_timer->adjust(attotime::from_ticks( 1, m_clock )); +} + + +void crtc_ega_device::set_clock(int clock) +{ + /* validate arguments */ + assert(clock > 0); + + if (clock != m_clock) + { + m_clock = clock; + recompute_parameters(true); + } +} + + +void crtc_ega_device::set_hpixels_per_column(int hpixels_per_column) +{ + /* validate arguments */ + assert(hpixels_per_column > 0); + + if (hpixels_per_column != m_hpixels_per_column) + { + m_hpixels_per_column = hpixels_per_column; + recompute_parameters(true); + } +} + + +void crtc_ega_device::update_cursor_state() +{ + /* save and increment cursor counter */ + UINT8 last_cursor_blink_count = m_cursor_blink_count; + m_cursor_blink_count = m_cursor_blink_count + 1; + + /* switch on cursor blinking mode */ + switch (m_cursor_start_ras & 0x60) + { + /* always on */ + case 0x00: m_cursor_state = true; break; + + /* always off */ + case 0x20: m_cursor_state = false; break; + + /* fast blink */ + case 0x40: + if ((last_cursor_blink_count & 0x10) != (m_cursor_blink_count & 0x10)) + { + m_cursor_state = !m_cursor_state; + } + break; + + /* slow blink */ + case 0x60: + if ((last_cursor_blink_count & 0x20) != (m_cursor_blink_count & 0x20)) + { + m_cursor_state = !m_cursor_state; + } + break; + } +} + + +UINT32 crtc_ega_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + assert(bitmap.valid()); + + if (m_has_valid_parameters) + { + UINT16 y; + + assert(!m_row_update_cb.isnull()); + + /* call the set up function if any */ + if (!m_begin_update_cb.isnull()) + m_begin_update_cb(bitmap, cliprect); + + if (cliprect.min_y == 0) + { + /* read the start address at the beginning of the frame */ + m_current_disp_addr = m_disp_start_addr; + } + + /* for each row in the visible region */ + for (y = cliprect.min_y; y <= cliprect.max_y; y++) + { + /* compute the current raster line */ + UINT8 ra = y % (m_max_ras_addr + 1); + + /* check if the cursor is visible and is on this scanline */ + int cursor_visible = m_cursor_state && + (ra >= (m_cursor_start_ras & 0x1f)) && + ( (ra <= (m_cursor_end_ras & 0x1f)) || ((m_cursor_end_ras & 0x1f) == 0x00 )) && + (m_cursor_addr >= m_current_disp_addr) && + (m_cursor_addr < (m_current_disp_addr + ( m_horiz_disp + 1 ))); + + /* compute the cursor X position, or -1 if not visible */ + INT8 cursor_x = cursor_visible ? (m_cursor_addr - m_current_disp_addr) : -1; + + /* call the external system to draw it */ + m_row_update_cb(bitmap, cliprect, m_current_disp_addr, ra, y, m_horiz_disp + 1, cursor_x); + + /* update MA if the last raster address */ + if (ra == m_max_ras_addr) + m_current_disp_addr = (m_current_disp_addr + m_horiz_disp + 1) & 0xffff; + } + + /* call the tear down function if any */ + if (!m_end_update_cb.isnull()) + m_end_update_cb(bitmap, cliprect); + } + else + logerror("Invalid crtc_ega screen parameters - display disabled!!!\n"); + + return 0; +} + + +/* device interface */ +void crtc_ega_device::device_start() +{ + /* validate arguments */ + assert(m_clock > 0); + assert(m_hpixels_per_column > 0); + + /* resolve callbacks */ + m_res_out_de_cb.resolve(); + m_res_out_hsync_cb.resolve(); + m_res_out_vsync_cb.resolve(); + m_res_out_vblank_cb.resolve(); + + /* bind delegates */ + m_begin_update_cb.bind_relative_to(*owner()); + m_row_update_cb.bind_relative_to(*owner()); + m_end_update_cb.bind_relative_to(*owner()); + + /* create the timers */ + m_line_timer = timer_alloc(TIMER_LINE); + m_de_off_timer = timer_alloc(TIMER_DE_OFF); + m_cur_on_timer = timer_alloc(TIMER_CUR_ON); + m_cur_off_timer = timer_alloc(TIMER_CUR_OFF); + m_hsync_on_timer = timer_alloc(TIMER_HSYNC_ON); + m_hsync_off_timer = timer_alloc(TIMER_HSYNC_OFF); + m_light_pen_latch_timer = timer_alloc(TIMER_LIGHT_PEN_LATCH); + + /* Use some large startup values */ + m_horiz_char_total = 0xff; + m_max_ras_addr = 0x1f; + m_vert_total = 0x3ff; + + m_ena_vert_access = 0; + m_de_skew = 0; + m_horiz_retr_start = 0; + m_horiz_retr_end = 0; + m_horiz_retr_skew = 0; + m_preset_row_scan = 0; + m_byte_panning = 0; + m_scan_doubling = 0; + m_cursor_start_ras = 0x20; + m_cursor_disable = 0; + m_cursor_end_ras = 0; + m_cursor_skew = 0; + m_disp_start_addr = 0; + m_light_pen_addr = 0; + m_vert_retr_end = 0; + m_protect = 0; + m_bandwidth = 0; + m_offset = 0; + m_underline_loc = 0; + m_vert_blank_end = 0; + m_mode_control = 0; + m_line_compare = 0; + m_register_address_latch = 0; + m_cursor_state = false; + m_cursor_blink_count = 0; + m_cur = 0; + m_hsync = 0; + m_vsync = 0; + m_vblank = 0; + m_de = 0; + m_character_counter = 0; + m_hsync_width_counter = 0; + m_vsync_width_counter = 0; + m_line_enable_ff = false; + m_vsync_ff = 0; + m_adjust_active = 0; + + m_current_disp_addr = 0; + m_light_pen_latched = FALSE; + m_has_valid_parameters = false; + + /* register for state saving */ + save_item(NAME(m_hpixels_per_column)); + save_item(NAME(m_register_address_latch)); + save_item(NAME(m_horiz_char_total)); + save_item(NAME(m_horiz_disp)); + save_item(NAME(m_horiz_blank_start)); + save_item(NAME(m_mode_control)); + save_item(NAME(m_cursor_start_ras)); + save_item(NAME(m_cursor_end_ras)); + save_item(NAME(m_disp_start_addr)); + save_item(NAME(m_cursor_addr)); + save_item(NAME(m_light_pen_addr)); + save_item(NAME(m_light_pen_latched)); + save_item(NAME(m_cursor_state)); + save_item(NAME(m_cursor_blink_count)); + save_item(NAME(m_horiz_blank_end)); + save_item(NAME(m_ena_vert_access)); + save_item(NAME(m_de_skew)); + save_item(NAME(m_horiz_retr_start)); + save_item(NAME(m_horiz_retr_end)); + save_item(NAME(m_horiz_retr_skew)); + save_item(NAME(m_vert_total)); + save_item(NAME(m_preset_row_scan)); + save_item(NAME(m_byte_panning)); + save_item(NAME(m_max_ras_addr)); + save_item(NAME(m_scan_doubling)); + save_item(NAME(m_cursor_disable)); + save_item(NAME(m_cursor_skew)); + save_item(NAME(m_vert_retr_start)); + save_item(NAME(m_vert_retr_end)); + save_item(NAME(m_protect)); + save_item(NAME(m_bandwidth)); + save_item(NAME(m_vert_disp_end)); + save_item(NAME(m_offset)); + save_item(NAME(m_underline_loc)); + save_item(NAME(m_vert_blank_start)); + save_item(NAME(m_vert_blank_end)); + save_item(NAME(m_line_compare)); +} + + +void crtc_ega_device::device_reset() +{ + /* internal registers other than status remain unchanged, all outputs go low */ + if (!m_res_out_de_cb.isnull()) + m_res_out_de_cb(false); + + if (!m_res_out_hsync_cb.isnull()) + m_res_out_hsync_cb(false); + + if (!m_res_out_vsync_cb.isnull()) + m_res_out_vsync_cb(false); + + if (!m_res_out_vblank_cb.isnull()) + m_res_out_vblank_cb(false); + + if (!m_line_timer->enabled()) + { + m_line_timer->adjust( attotime::from_ticks( m_horiz_char_total + 2, m_clock ) ); + } + + m_light_pen_latched = false; + + m_cursor_addr = 0; + m_line_address = 0; + m_horiz_disp = 0; + m_cursor_x = 0; + m_horiz_blank_start = 0; + m_horiz_blank_end = 0; + m_vert_disp_end = 0; + m_vert_retr_start = 0; + m_vert_blank_start = 0; + m_line_counter = 0; + m_raster_counter = 0; + m_horiz_pix_total = 0; + m_vert_pix_total = 0; + m_max_visible_x = 0; + m_max_visible_y = 0; + m_hsync_on_pos = 0; + m_vsync_on_pos = 0; + m_hsync_off_pos = 0; + m_vsync_off_pos = 0; +} |