From f652d21e167265bded620fab397f142d18bd7b45 Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Mon, 6 Nov 2017 20:28:54 +0300 Subject: 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. --- src/devices/video/i8275.cpp | 130 +++++++++++++++++++++++++++----------------- src/devices/video/i8275.h | 1 + 2 files changed, 80 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!"); } diff --git a/src/devices/video/i8275.h b/src/devices/video/i8275.h index 06a6495698d..a2a8715972c 100644 --- a/src/devices/video/i8275.h +++ b/src/devices/video/i8275.h @@ -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; -- cgit v1.2.3