mc6845: improve the cursor emulation

Implements partial cursors.
This commit is contained in:
68bit 2019-08-26 20:00:42 +10:00
parent 6bf0a5c8bb
commit b88b6693a5
4 changed files with 44 additions and 57 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 */
}