summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/maria.c
diff options
context:
space:
mode:
author Fabio Priuli <etabeta78@users.noreply.github.com>2014-10-10 05:03:12 +0000
committer Fabio Priuli <etabeta78@users.noreply.github.com>2014-10-10 05:03:12 +0000
commit9f7b18a05caeae64e5ee337158771436a1bca646 (patch)
treefe8654a6a8dd14b9eb176438561f33b73fc833e2 /src/mess/video/maria.c
parent0ed3636613eb16a8513bdc2459742eb8d3b4e614 (diff)
(MESS) maria.c: improved DMA accuracy. [Mike Saarna, Robert Tuccitto]
- Last Line DMA value corrected to 6. GCC and Atari docs both show a difference between Other Line and Last Line as +6 at the lowest part of the range. - Blank scanlines are drawn when DMA is off, like real hardware. - If MARIA hits the DMA limit, the CPU doesn't run until the next scanline.
Diffstat (limited to 'src/mess/video/maria.c')
-rw-r--r--src/mess/video/maria.c183
1 files changed, 102 insertions, 81 deletions
diff --git a/src/mess/video/maria.c b/src/mess/video/maria.c
index 55fe067ec73..5f285e4b2bf 100644
--- a/src/mess/video/maria.c
+++ b/src/mess/video/maria.c
@@ -4,8 +4,17 @@
- some history:
- 2014-10-03 Mike Saarna, Robert Tuccitto reorganized DMA penalties to
- support new rendering timeout code.
+ 2014-10-05 Mike Saarna, Robert Tuccitto Last Line DMA value corrected
+ to 6. GCC and Atari docs both show a difference between
+ Other Line and Last Line as +6 at the lowest part of the
+ range.
+ Blank scanlines are drawn when DMA is off, like real
+ hardware.
+ If MARIA hits the DMA limit, the CPU doesn't run until
+ the next scanline.
+
+ 2014-09-03 Mike Saarna, Robert Tuccitto reorganized DMA penalties to
+ support new rendering timeout code.
2014-08-29 Mike Saarna Timeout rendering added.
@@ -165,103 +174,115 @@ void atari_maria_device::draw_scanline()
int d, c, pixel_cell, cells;
int maria_cycles;
- // All lines in a zone have the same initial DMA startup time. We'll adjust
- // cycles for the special last zone line later, as those penalties happen after
- // MARIA is done rendering, or after its hit the maximum rendering time.
- maria_cycles = 16;
-
cells = 0;
- /* Process this DLL entry */
- dl = m_dl;
+ if(m_dmaon)
+ {
+ // All lines in a zone have the same initial DMA startup time. We'll adjust
+ // cycles for the special last zone line later, as those penalties happen after
+ // MARIA is done rendering, or after its hit the maximum rendering time.
+ maria_cycles = 16;
- /* DMA */
- /* Step through DL's while we're within maximum rendering time. max render time = ( scanline length - DMA start ) */
- /* 426 = ( 454 - 28 ) */
- while (((READ_MEM(dl + 1) & 0x5f) != 0) && (maria_cycles<426))
- {
- /* Extended header */
- if (!(READ_MEM(dl + 1) & 0x1f))
- {
- graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
- width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1;
- hpos = READ_MEM(dl + 4);
- pal = READ_MEM(dl + 3) >> 5;
- m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5;
- ind = READ_MEM(dl + 1) & 0x20;
- dl += 5;
- maria_cycles += 10;
- }
- /* Normal header */
- else
- {
- graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
- width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1;
- hpos = READ_MEM(dl + 3);
- pal = READ_MEM(dl + 1) >> 5;
- ind = 0x00;
- dl += 4;
- maria_cycles += 8;
- }
+ /* Process this DLL entry */
+ dl = m_dl;
- /*logerror("%x DL: ADR=%x width=%x hpos=%x pal=%x mode=%x ind=%x\n", m_screen->vpos(), graph_adr, width, hpos, pal, m_write_mode, ind);*/
+ /* DMA */
+ /* Step through DL's while we're within maximum rendering time. */
+ /* max render time = ( scanline length - DMA start ) */
+ /* 426 = ( 454 - 28 ) */
- for (int x = 0; x < width; x++)
+ while (((READ_MEM(dl + 1) & 0x5f) != 0) && (maria_cycles<426))
{
- if (maria_cycles >= 426) // ensure we haven't overrun the maximum render time
- break;
+ /* Extended header */
+ if (!(READ_MEM(dl + 1) & 0x1f))
+ {
+ graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
+ width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1;
+ hpos = READ_MEM(dl + 4);
+ pal = READ_MEM(dl + 3) >> 5;
+ m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5;
+ ind = READ_MEM(dl + 1) & 0x20;
+ dl += 5;
+ maria_cycles += 10;
+ }
+ /* Normal header */
+ else
+ {
+ graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
+ width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1;
+ hpos = READ_MEM(dl + 3);
+ pal = READ_MEM(dl + 1) >> 5;
+ ind = 0x00;
+ dl += 4;
+ maria_cycles += 8;
+ }
- /* Do indirect mode */
- if (ind)
+ /*logerror("%x DL: ADR=%x width=%x hpos=%x pal=%x mode=%x ind=%x\n", m_screen->vpos(), graph_adr, width, hpos, pal, m_write_mode, ind);*/
+
+ for (int x = 0; x < width; x++)
{
- c = READ_MEM(graph_adr + x) & 0xff;
- data_addr = (m_charbase | c) + (m_offset << 8);
- if (is_holey(data_addr))
- continue;
-
- maria_cycles += 3;
- if (m_cwidth) // two data bytes per map byte
+ if (maria_cycles >= 426) // ensure we haven't overrun the maximum render time
+ break;
+
+ /* Do indirect mode */
+ if (ind)
{
- cells = write_line_ram(data_addr, hpos, pal);
- hpos += cells;
- cells = write_line_ram(data_addr+1, hpos, pal);
- hpos += cells;
- maria_cycles += 6;
+ c = READ_MEM(graph_adr + x) & 0xff;
+ data_addr = (m_charbase | c) + (m_offset << 8);
+ if (is_holey(data_addr))
+ continue;
+
+ maria_cycles += 3;
+ if (m_cwidth) // two data bytes per map byte
+ {
+ cells = write_line_ram(data_addr, hpos, pal);
+ hpos += cells;
+ cells = write_line_ram(data_addr+1, hpos, pal);
+ hpos += cells;
+ maria_cycles += 6;
+ }
+ else
+ {
+ cells = write_line_ram(data_addr, hpos, pal);
+ hpos += cells;
+ maria_cycles += 3;
+ }
}
- else
+ else // direct mode
{
+ data_addr = graph_adr + x + (m_offset << 8);
+ if (is_holey(data_addr))
+ continue;
cells = write_line_ram(data_addr, hpos, pal);
hpos += cells;
maria_cycles += 3;
}
}
- else // direct mode
- {
- data_addr = graph_adr + x + (m_offset << 8);
- if (is_holey(data_addr))
- continue;
- cells = write_line_ram(data_addr, hpos, pal);
- hpos += cells;
- maria_cycles += 3;
- }
}
- }
- // Last Line post-render DMA cycle penalties...
- if (m_offset == 0)
- {
- maria_cycles += 3; // extra shutdown time
- if (READ_MEM(m_dll + 3) & 0x80)
- maria_cycles += 21; // interrupt overhead
- }
+ // Last Line post-render DMA cycle penalties...
+ if (m_offset == 0)
+ {
+ maria_cycles += 6; // extra shutdown time
+ if (READ_MEM(m_dll + 3) & 0x80)
+ maria_cycles += 17; // interrupt overhead
+ }
- // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
- // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
- // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
- // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
- if (!m_wsync)
- m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4));
+ // If MARIA used up all of the DMA time then the CPU can't run until next line...
+ if (maria_cycles>=426)
+ {
+ m_cpu->spin_until_trigger(TRIGGER_HSYNC);
+ m_wsync = 1;
+ }
+
+ // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
+ // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
+ // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
+ // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
+ if (!m_wsync)
+ m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4));
+ }
// draw line buffer to screen
m_active_buffer = !m_active_buffer; // switch buffers
@@ -335,13 +356,13 @@ void atari_maria_device::startdma(int lines)
m_holey = (READ_MEM(m_dll) & 0x60) >> 5;
m_nmi = READ_MEM(m_dll) & 0x80;
/* logerror("DLL=%x\n",m_dll); */
- draw_scanline();
}
+ if ((frame_scanline > 15) && (frame_scanline < (lines - 5)))
+ draw_scanline();
if ((frame_scanline > 16) && (frame_scanline < (lines - 5)) && m_dmaon)
{
- draw_scanline();
if (m_offset == 0)
{
m_dll += 3;