i8275: handle invisible field attributes and "end of row - stop dma" special code better; honor Video Enable bit.

Fixes MT05764.  No visual change on mikromik, tim100, zorba, and radio86 clones.
This commit is contained in:
Sergey Svishchev 2017-11-06 20:28:54 +03:00 committed by Vas Crabb
parent e0ac072a29
commit f652d21e16
2 changed files with 77 additions and 48 deletions

View File

@ -11,6 +11,9 @@
TODO:
- double spaced rows
- blanking of top and bottom rows when underline MSB is set
- end of row/screen - stop dma
- preset counters
*/
@ -106,6 +109,8 @@ i8275_device::i8275_device(const machine_config &mconfig, const char *tag, devic
m_param_idx(0),
m_param_end(0),
m_buffer_idx(0),
m_fifo_idx(0),
m_dma_idx(0),
m_fifo_next(false),
m_buffer_dma(0),
m_lpen(0),
@ -156,6 +161,7 @@ void i8275_device::device_start()
save_item(NAME(m_buffer[1]));
save_item(NAME(m_buffer_idx));
save_item(NAME(m_fifo_idx));
save_item(NAME(m_dma_idx));
save_item(NAME(m_fifo_next));
save_item(NAME(m_buffer_dma));
save_item(NAME(m_lpen));
@ -215,8 +221,6 @@ void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param,
break;
case TIMER_SCANLINE:
if (!(m_status & ST_VE)) break;
//LOG("I8275 y %u x %u HRTC 0\n", y, x);
m_write_hrtc(0);
@ -226,11 +230,11 @@ void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param,
m_write_vrtc(0);
}
if (m_scanline <= (m_vrtc_scanline - SCANLINES_PER_ROW))
if ((m_status & ST_VE) && m_scanline <= (m_vrtc_scanline - SCANLINES_PER_ROW))
{
if (lc == 0)
{
if (m_buffer_idx < CHARACTERS_PER_ROW)
if (m_dma_idx < CHARACTERS_PER_ROW)
{
m_status |= ST_DU;
m_du = true;
@ -246,6 +250,7 @@ void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param,
m_buffer_dma = !m_buffer_dma;
m_buffer_idx = 0;
m_fifo_idx = 0;
m_dma_idx = 0;
if ((m_scanline < (m_vrtc_scanline - SCANLINES_PER_ROW)))
{
@ -271,37 +276,41 @@ void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param,
//LOG("I8275 y %u x %u VRTC 1\n", y, x);
m_write_vrtc(1);
// reset field attributes
m_hlgt = 0;
m_vsp = 0;
m_gpa = 0;
m_rvv = 0,
m_lten = 0;
if (m_status & ST_VE)
{
// reset field attributes
m_hlgt = 0;
m_vsp = 0;
m_gpa = 0;
m_rvv = 0;
m_lten = 0;
m_du = false;
m_dma_stop = false;
m_end_of_screen = false;
m_du = false;
m_dma_stop = false;
m_end_of_screen = false;
m_cursor_blink++;
m_cursor_blink &= 0x1f;
m_cursor_blink++;
m_cursor_blink &= 0x1f;
m_char_blink++;
m_char_blink &= 0x3f;
m_stored_attr = 0;
m_char_blink++;
m_char_blink &= 0x3f;
m_stored_attr = 0;
}
}
if (m_scanline == m_vrtc_drq_scanline)
if ((m_status & ST_VE) && m_scanline == m_vrtc_drq_scanline)
{
// swap line buffers
m_buffer_dma = !m_buffer_dma;
m_buffer_idx = 0;
m_fifo_idx = 0;
m_dma_idx = 0;
// start DMA burst
m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE));
}
if (m_scanline < m_vrtc_scanline)
if ((m_status & ST_VE) && m_scanline < m_vrtc_scanline)
{
int line_counter = OFFSET_LINE_COUNTER ? ((lc - 1) % SCANLINES_PER_ROW) : lc;
bool end_of_row = false;
@ -493,24 +502,41 @@ WRITE8_MEMBER( i8275_device::write )
switch (data >> 5)
{
/*
* DMA requests stop;
* IE is reset, interrupts are disabled;
* VE is reset, VSP output is used to blank the screen;
* HRTC and VRTC continue to run;
* HRTC and VRTC timing are random on power-up.
*/
case CMD_RESET:
LOG("I8275 Reset\n");
m_status &= ~ST_IE;
m_status &= ~(ST_IE | ST_VE);
LOG("I8275 IRQ 0\n");
m_write_irq(CLEAR_LINE);
m_write_drq(0);
m_drq_on_timer->adjust(attotime::zero);
m_param_idx = REG_SCN1;
m_param_end = REG_SCN4;
break;
/*
* IE is set, interrupts are enabled;
* VE is set, video is enabled;
* DMA requests begin.
*/
case CMD_START_DISPLAY:
m_param[REG_DMA] = data;
LOG("I8275 Start Display %u %u\n", DMA_BURST_COUNT, DMA_BURST_SPACE);
m_status |= (ST_IE | ST_VE);
break;
/*
* interrupts remain enabled;
* HRTC and VRTC continue to run.
*/
case CMD_STOP_DISPLAY:
LOG("I8275 Stop Display\n");
m_status &= ~ST_VE;
@ -540,7 +566,6 @@ WRITE8_MEMBER( i8275_device::write )
case CMD_PRESET_COUNTERS:
LOG("I8275 Preset Counters\n");
m_scanline = 0;
break;
}
}
@ -566,7 +591,7 @@ WRITE8_MEMBER( i8275_device::write )
WRITE8_MEMBER( i8275_device::dack_w )
{
//LOG("I8275 y %u x %u DACK %04x:%02x %u\n", screen().vpos(), screen().hpos(), offset, data, m_buffer_idx);
//LOG("I8275 y %u x %u DACK %04x:%02x %u (%u)\n", screen().vpos(), screen().hpos(), offset, data, m_buffer_idx, m_dma_idx);
m_write_drq(0);
@ -584,41 +609,43 @@ WRITE8_MEMBER( i8275_device::dack_w )
}
else
{
if (m_buffer_idx < ARRAY_LENGTH(m_buffer[m_buffer_dma]))
if (m_dma_idx < ARRAY_LENGTH(m_buffer[m_buffer_dma]))
m_buffer[m_buffer_dma][m_buffer_idx++] = data;
if (!VISIBLE_FIELD_ATTRIBUTE && ((data & 0xc0) == 0x80))
{
m_fifo_next = true;
}
}
switch (data)
m_dma_idx++;
switch (data)
{
case SCC_END_OF_ROW_DMA:
// stop DMA
// TODO should read one more character if DMA burst not completed
m_drq_on_timer->adjust(screen().time_until_pos(screen().vpos() + 1, 0));
break;
case SCC_END_OF_SCREEN_DMA:
m_dma_stop = true;
// TODO should read one more character if DMA burst not completed
break;
default:
if (m_dma_idx == CHARACTERS_PER_ROW)
{
case SCC_END_OF_ROW_DMA:
// stop DMA
// TODO should read one more character if DMA burst not completed
break;
case SCC_END_OF_SCREEN_DMA:
m_dma_stop = true;
// TODO should read one more character if DMA burst not completed
break;
default:
if (m_buffer_idx == CHARACTERS_PER_ROW)
{
// stop DMA
}
else if (!(m_buffer_idx % DMA_BURST_COUNT))
{
m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE));
}
else
{
m_drq_on_timer->adjust(attotime::zero);
}
}
else if (!(m_dma_idx % DMA_BURST_COUNT))
{
m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE));
}
else
{
m_drq_on_timer->adjust(attotime::zero);
}
}
}
@ -688,6 +715,7 @@ void i8275_device::recompute_parameters()
LOG("irq_y %u vrtc_y %u drq_y %u\n", m_irq_scanline, m_vrtc_scanline, m_vrtc_drq_scanline);
m_scanline_timer->adjust(screen().time_until_pos(0, 0), 0, screen().scan_period());
m_scanline = 0;
if (DOUBLE_SPACED_ROWS) fatalerror("Double spaced rows not supported!");
}

View File

@ -197,6 +197,7 @@ protected:
uint8_t m_fifo[2][16];
int m_buffer_idx;
int m_fifo_idx;
int m_dma_idx;
bool m_fifo_next;
int m_buffer_dma;