summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/i8275.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/i8275.cpp')
-rw-r--r--src/devices/video/i8275.cpp130
1 files changed, 79 insertions, 51 deletions
diff --git a/src/devices/video/i8275.cpp b/src/devices/video/i8275.cpp
index c962768e17f..50a0be52a45 100644
--- a/src/devices/video/i8275.cpp
+++ b/src/devices/video/i8275.cpp
@@ -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;
-
- m_du = false;
- m_dma_stop = false;
- m_end_of_screen = false;
-
- m_cursor_blink++;
- m_cursor_blink &= 0x1f;
-
- m_char_blink++;
- m_char_blink &= 0x3f;
- m_stored_attr = 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_cursor_blink++;
+ m_cursor_blink &= 0x1f;
+
+ 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)
- {
- case SCC_END_OF_ROW_DMA:
- // stop DMA
- // TODO should read one more character if DMA burst not completed
- break;
+ m_dma_idx++;
- case SCC_END_OF_SCREEN_DMA:
- m_dma_stop = true;
- // TODO should read one more character if DMA burst not completed
- break;
+ 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;
- 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);
- }
- }
+ 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)
+ {
+ // stop DMA
+ }
+ 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!");
}