Previous 199869 Revisions Next

r32612 Friday 10th October, 2014 at 05:03:12 UTC by Fabio Priuli
(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.
[src/mess/video]maria.c

trunk/src/mess/video/maria.c
r32611r32612
44
55 
66  - some history:
7    2014-10-03 Mike Saarna, Robert Tuccitto reorganized DMA penalties to
8            support new rendering timeout code.
7    2014-10-05 Mike Saarna, Robert Tuccitto Last Line DMA value corrected
8                to 6. GCC and Atari docs both show a difference between
9                Other Line and Last Line as +6 at the lowest part of the
10                range.
11                Blank scanlines are drawn when DMA is off, like real
12                hardware.
13                If MARIA hits the DMA limit, the CPU doesn't run until
14                the next scanline.
915
16    2014-09-03 Mike Saarna, Robert Tuccitto reorganized DMA penalties to
17                support new rendering timeout code.
18
1019    2014-08-29 Mike Saarna Timeout rendering added.
1120 
1221    2014-08-26 Fabio Priuli Converted to device
r32611r32612
165174   int d, c, pixel_cell, cells;
166175   int maria_cycles;
167176
168   // All lines in a zone have the same initial DMA startup time. We'll adjust
169   // cycles for the special last zone line later, as those penalties happen after
170   // MARIA is done rendering, or after its hit the maximum rendering time.
171   maria_cycles = 16;
172
173177   cells = 0;
174178
175   /* Process this DLL entry */
176   dl = m_dl;
179   if(m_dmaon)
180   {
181      // All lines in a zone have the same initial DMA startup time. We'll adjust
182      // cycles for the special last zone line later, as those penalties happen after
183      // MARIA is done rendering, or after its hit the maximum rendering time.
184      maria_cycles = 16;
177185
178   /* DMA */
179   /* Step through DL's while we're within maximum rendering time.   max render time = ( scanline length - DMA start ) */
180   /*                                                                   426          = (     454         -     28    ) */
181186
182   while (((READ_MEM(dl + 1) & 0x5f) != 0) && (maria_cycles<426))
183   {
184      /* Extended header */
185      if (!(READ_MEM(dl + 1) & 0x1f))
186      {
187         graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
188         width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1;
189         hpos = READ_MEM(dl + 4);
190         pal = READ_MEM(dl + 3) >> 5;
191         m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5;
192         ind = READ_MEM(dl + 1) & 0x20;
193         dl += 5;
194         maria_cycles += 10;
195      }
196      /* Normal header */
197      else
198      {
199         graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
200         width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1;
201         hpos = READ_MEM(dl + 3);
202         pal = READ_MEM(dl + 1) >> 5;
203         ind = 0x00;
204         dl += 4;
205         maria_cycles += 8;
206      }
187      /* Process this DLL entry */
188      dl = m_dl;
207189
208      /*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);*/
190      /* DMA */
191      /* Step through DL's while we're within maximum rendering time. */
192      /*  max render time = ( scanline length - DMA start ) */
193      /*     426          = (     454         -     28    ) */
209194
210      for (int x = 0; x < width; x++)
195      while (((READ_MEM(dl + 1) & 0x5f) != 0) && (maria_cycles<426))
211196      {
212         if (maria_cycles >= 426) // ensure we haven't overrun the maximum render time
213            break;
197         /* Extended header */
198         if (!(READ_MEM(dl + 1) & 0x1f))
199         {
200            graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
201            width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1;
202            hpos = READ_MEM(dl + 4);
203            pal = READ_MEM(dl + 3) >> 5;
204            m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5;
205            ind = READ_MEM(dl + 1) & 0x20;
206            dl += 5;
207            maria_cycles += 10;
208         }
209         /* Normal header */
210         else
211         {
212            graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
213            width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1;
214            hpos = READ_MEM(dl + 3);
215            pal = READ_MEM(dl + 1) >> 5;
216            ind = 0x00;
217            dl += 4;
218            maria_cycles += 8;
219         }
214220
215         /* Do indirect mode */
216         if (ind)
221         /*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);*/
222
223         for (int x = 0; x < width; x++)
217224         {
218            c = READ_MEM(graph_adr + x) & 0xff;
219            data_addr = (m_charbase | c) + (m_offset << 8);
220            if (is_holey(data_addr))
221               continue;
225            if (maria_cycles >= 426) // ensure we haven't overrun the maximum render time
226               break;
227
228            /* Do indirect mode */
229            if (ind)
230            {
231               c = READ_MEM(graph_adr + x) & 0xff;
232               data_addr = (m_charbase | c) + (m_offset << 8);
233               if (is_holey(data_addr))
234                  continue;
222235           
223            maria_cycles += 3;
224            if (m_cwidth) // two data bytes per map byte
225            {
226               cells = write_line_ram(data_addr, hpos, pal);
227               hpos += cells;
228               cells = write_line_ram(data_addr+1, hpos, pal);
229               hpos += cells;
230               maria_cycles += 6;
236               maria_cycles += 3;
237               if (m_cwidth) // two data bytes per map byte
238               {
239                  cells = write_line_ram(data_addr, hpos, pal);
240                  hpos += cells;
241                  cells = write_line_ram(data_addr+1, hpos, pal);
242                  hpos += cells;
243                  maria_cycles += 6;
244               }
245               else
246               {
247                  cells = write_line_ram(data_addr, hpos, pal);
248                  hpos += cells;
249                  maria_cycles += 3;
250               }
231251            }
232            else
252            else // direct mode
233253            {
254               data_addr = graph_adr + x + (m_offset  << 8);
255               if (is_holey(data_addr))
256                  continue;
234257               cells = write_line_ram(data_addr, hpos, pal);
235258               hpos += cells;
236259               maria_cycles += 3;
237260            }
238261         }
239         else // direct mode
240         {
241            data_addr = graph_adr + x + (m_offset  << 8);
242            if (is_holey(data_addr))
243               continue;
244            cells = write_line_ram(data_addr, hpos, pal);
245            hpos += cells;
246            maria_cycles += 3;
247         }
248262      }
249   }
250263   
251   // Last Line post-render DMA cycle penalties...
252   if (m_offset == 0)
253   {
254      maria_cycles += 3; // extra shutdown time
255      if (READ_MEM(m_dll + 3) & 0x80)
256         maria_cycles += 21; // interrupt overhead
264      // Last Line post-render DMA cycle penalties...
265      if (m_offset == 0)
266      {
267         maria_cycles += 6; // extra shutdown time
268         if (READ_MEM(m_dll + 3) & 0x80)
269            maria_cycles += 17; // interrupt overhead
270      }
271
272      // If MARIA used up all of the DMA time then the CPU can't run until next line...
273      if (maria_cycles>=426)
274      {
275         m_cpu->spin_until_trigger(TRIGGER_HSYNC);
276         m_wsync = 1;
277      }
278
279      // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
280      // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
281      // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
282      // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
283      if (!m_wsync)
284         m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4));
257285   }
258286
259   // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
260   // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
261   // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
262   // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
263   if (!m_wsync)
264      m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4));
265
266287   // draw line buffer to screen
267288   m_active_buffer = !m_active_buffer; // switch buffers
268289   UINT16 *scanline;
r32611r32612
335356      m_holey = (READ_MEM(m_dll) & 0x60) >> 5;
336357      m_nmi = READ_MEM(m_dll) & 0x80;
337358      /*  logerror("DLL=%x\n",m_dll); */
338      draw_scanline();
339359   }
340360
361   if ((frame_scanline > 15) && (frame_scanline < (lines - 5)))
362      draw_scanline();
341363
342364   if ((frame_scanline > 16) && (frame_scanline < (lines - 5)) && m_dmaon)
343365   {
344      draw_scanline();
345366      if (m_offset == 0)
346367      {
347368         m_dll += 3;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team