From b88b6693a58f90b5e2260a37c88fd0b75c51489c Mon Sep 17 00:00:00 2001 From: 68bit Date: Mon, 26 Aug 2019 20:00:42 +1000 Subject: mc6845: improve the cursor emulation Implements partial cursors. --- src/devices/video/mc6845.cpp | 54 ++++++++++++++++++++++++++++++++++---------- src/devices/video/mc6845.h | 1 + src/mame/includes/kaypro.h | 2 -- src/mame/video/kaypro.cpp | 44 +----------------------------------- 4 files changed, 44 insertions(+), 57 deletions(-) diff --git a/src/devices/video/mc6845.cpp b/src/devices/video/mc6845.cpp index bfb3cb249eb..ae79b01292e 100644 --- a/src/devices/video/mc6845.cpp +++ b/src/devices/video/mc6845.cpp @@ -692,6 +692,42 @@ bool mc6845_device::match_line() } +bool mc6845_device::check_cursor_visible(uint16_t ra, uint16_t line_addr) +{ + if (!m_cursor_state) + return false; + + if ((m_cursor_addr < line_addr) || + (m_cursor_addr >= (line_addr + m_horiz_disp))) + { + // Not a cursor character line. + return false; + } + + uint16_t cursor_start_ras = m_cursor_start_ras & 0x1f; + + if (cursor_start_ras > m_max_ras_addr) + { + // No cursor possible. + return false; + } + + if (cursor_start_ras <= m_cursor_end_ras) + { + if (m_cursor_end_ras > m_max_ras_addr) + { + // Full cursor. + return true; + } + // Cursor from start to end inclusive. + return (ra >= cursor_start_ras) && (ra <= m_cursor_end_ras); + } + + // Otherwise cursor_start_ras > m_cursor_end_ras giving a split cursor. + return (ra <= m_cursor_end_ras) || (ra >= cursor_start_ras); +} + + void mc6845_device::handle_line_timer() { bool new_vsync = m_vsync; @@ -776,11 +812,7 @@ void mc6845_device::handle_line_timer() m_de_off_timer->adjust(cclks_to_attotime(m_horiz_disp)); /* 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)) ) + if (check_cursor_visible(m_raster_counter, m_line_address)) { m_cursor_x = m_cursor_addr - m_line_address; @@ -969,14 +1001,12 @@ uint8_t mc6845_device::draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangl /* compute the current raster line */ uint8_t ra = y % (m_max_ras_addr + (MODE_INTERLACE_AND_VIDEO ? m_interlace_adjust : m_noninterlace_adjust)); - /* 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) && - (m_cursor_addr >= m_current_disp_addr) && - (m_cursor_addr < (m_current_disp_addr + m_horiz_disp)); + // Check if the cursor is visible and is on this scanline. + int cursor_visible = check_cursor_visible(ra, m_current_disp_addr); - /* compute the cursor X position, or -1 if not visible */ + // Compute the cursor X position, or -1 if not visible. This position + // is in units of characters and is relative to the start of the + // displayable area, not relative to the screen bitmap origin. int8_t cursor_x = cursor_visible ? (m_cursor_addr - m_current_disp_addr) : -1; int de = (y < m_max_visible_y) ? 1 : 0; int vbp = m_vert_pix_total - m_vsync_off_pos; diff --git a/src/devices/video/mc6845.h b/src/devices/video/mc6845.h index a75cb62a205..2ff2b663779 100644 --- a/src/devices/video/mc6845.h +++ b/src/devices/video/mc6845.h @@ -235,6 +235,7 @@ protected: void set_vsync(int state); void set_cur(int state); bool match_line(); + bool check_cursor_visible(uint16_t ra, uint16_t line_addr); void handle_line_timer(); virtual void update_cursor_state(); virtual uint8_t draw_scanline(int y, bitmap_rgb32 &bitmap, const rectangle &cliprect); diff --git a/src/mame/includes/kaypro.h b/src/mame/includes/kaypro.h index aa676b26fb6..03cbe8296b3 100644 --- a/src/mame/includes/kaypro.h +++ b/src/mame/includes/kaypro.h @@ -79,11 +79,9 @@ public: void kaypro_map(address_map &map); void kayproii_io(address_map &map); private: - void mc6845_cursor_configure(); void mc6845_screen_configure(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - uint8_t m_mc6845_cursor[16]; uint8_t m_mc6845_reg[32]; uint8_t m_mc6845_ind; uint8_t m_framecnt; diff --git a/src/mame/video/kaypro.cpp b/src/mame/video/kaypro.cpp index d3de6878b61..418fe519f17 100644 --- a/src/mame/video/kaypro.cpp +++ b/src/mame/video/kaypro.cpp @@ -145,7 +145,7 @@ MC6845_UPDATE_ROW( kaypro_state::kaypro484_update_row ) for (x = 0; x < x_count; x++) // for each character { uint8_t inv=0; - // if (x == cursor_x) inv=0xff; /* uncomment when mame fixed */ + if (x == cursor_x) inv=0xff; uint16_t mem = (ma + x) & 0x7ff; uint8_t chr = m_p_videoram[mem]; uint8_t attr = m_p_videoram[mem | 0x800]; @@ -177,10 +177,6 @@ MC6845_UPDATE_ROW( kaypro_state::kaypro484_update_row ) if ( (BIT(attr, 2)) & (BIT(m_framecnt, 3)) ) fg = bg; - /* process cursor */ - if (x == cursor_x) - inv ^= m_mc6845_cursor[ra]; - /* get pattern of pixels for that character scanline */ if ( (ra == 15) & (BIT(attr, 3)) ) /* underline */ gfx = 0xff; @@ -201,41 +197,6 @@ MC6845_UPDATE_ROW( kaypro_state::kaypro484_update_row ) /************************************* MC6845 SUPPORT ROUTINES ***************************************/ -/* The 6845 can produce a variety of cursor shapes - all are emulated here - remove when mame fixed */ -void kaypro_state::mc6845_cursor_configure() -{ - uint8_t i,curs_type=0,r9,r10,r11; - - /* curs_type holds the general cursor shape to be created - 0 = no cursor - 1 = partial cursor (only shows on a block of scan lines) - 2 = full cursor - 3 = two-part cursor (has a part at the top and bottom with the middle blank) */ - - for ( i = 0; i < ARRAY_LENGTH(m_mc6845_cursor); i++) m_mc6845_cursor[i] = 0; // prepare cursor by erasing old one - - r9 = m_mc6845_reg[9]; // number of scan lines - 1 - r10 = m_mc6845_reg[10] & 0x1f; // cursor start line = last 5 bits - r11 = m_mc6845_reg[11]+1; // cursor end line incremented to suit for-loops below - - /* decide the curs_type by examining the registers */ - if (r10 < r11) curs_type=1; // start less than end, show start to end - else - if (r10 == r11) curs_type=2; // if equal, show full cursor - else curs_type=3; // if start greater than end, it's a two-part cursor - - if ((r11 - 1) > r9) curs_type=2; // if end greater than scan-lines, show full cursor - if (r10 > r9) curs_type=0; // if start greater than scan-lines, then no cursor - if (r11 > 16) r11=16; // truncate 5-bit register to fit our 4-bit hardware - - /* create the new cursor */ - if (curs_type > 1) for (i = 0;i < ARRAY_LENGTH(m_mc6845_cursor);i++) m_mc6845_cursor[i]=0xff; // turn on full cursor - - if (curs_type == 1) for (i = r10;i < r11;i++) m_mc6845_cursor[i]=0xff; // for each line that should show, turn on that scan line - - if (curs_type == 3) for (i = r11; i < r10;i++) m_mc6845_cursor[i]=0; // now take a bite out of the middle -} - /* Resize the screen within the limits of the hardware. Expand the image to fill the screen area. Standard screen is 640 x 400 = 0x7d0 bytes. */ @@ -280,9 +241,6 @@ WRITE8_MEMBER( kaypro_state::kaypro484_register_w ) if ((m_mc6845_ind == 1) || (m_mc6845_ind == 6) || (m_mc6845_ind == 9)) mc6845_screen_configure(); /* adjust screen size */ - if ((m_mc6845_ind > 8) && (m_mc6845_ind < 12)) - mc6845_cursor_configure(); /* adjust cursor shape - remove when mame fixed */ - if ((m_mc6845_ind > 17) && (m_mc6845_ind < 20)) m_mc6845_video_address = m_mc6845_reg[19] | ((m_mc6845_reg[18] & 0x3f) << 8); /* internal ULA address */ } -- cgit v1.2.3