Previous 199869 Revisions Next

r21805 Monday 11th March, 2013 at 19:28:59 UTC by Wilbert Pol
315_5124.c: Improved triggering of IRQs.  [Enik Land]

(MESS) sms.c:  [Enik Land]
- Fixed master clock speed for PAL machines.
- Improved hcount handling resulting in better results from
 Flubba's VDP timing checks.
[src/emu/video]315_5124.c 315_5124.h
[src/mess/drivers]sms.c
[src/mess/machine]sms.c

trunk/src/emu/video/315_5124.c
r21804r21805
5454#define STATUS_SPRCOL         0x20  /* Object collision flag */
5555#define STATUS_HINT           0x02  /* Pending horizontal interrupt flag */
5656
57#define VINT_HPOS             23
58#define HINT_HPOS             23
59#define VCOUNT_CHANGE_HPOS    22
60#define VINT_FLAG_HPOS        7
61#define SPROVR_HPOS           6
62#define SPRCOL_BASEHPOS       42
63#define DISPLAY_CB_HPOS       5  /* fix X-Scroll latchtime (Flubba's VDPTest) */
57#define VINT_HPOS             24
58#define VINT_FLAG_HPOS        23
59#define HINT_HPOS             25
60#define VCOUNT_CHANGE_HPOS    23
61#define SPROVR_HPOS           23
62#define SPRCOL_BASEHPOS       59
63#define DISPLAY_CB_HPOS       6  /* fix X-Scroll latchtime (Flubba's VDPTest) */
6464
6565#define DRAW_TIME_GG        86      /* 1 + 2 + 14 +8 + 96/2 */
6666#define DRAW_TIME_SMS       0
r21804r21805
294294      draw_scanline( SEGA315_5124_LBORDER_START + SEGA315_5124_LBORDER_WIDTH, param, m_screen->vpos() - param );
295295      break;
296296
297   case TIMER_SET_STATUS_VINT:
298      m_status |= STATUS_VINT;
299      break;
300
301   case TIMER_SET_STATUS_SPROVR:
302      m_status |= STATUS_SPROVR;
303      break;
304
305   case TIMER_SET_STATUS_SPRCOL:
306      m_status |= STATUS_SPRCOL;
307      break;
308
309297   case TIMER_CHECK_HINT:
310      if (m_line_counter == 0x00)
298      if ((m_pending_status & STATUS_HINT) || (m_status & STATUS_HINT))
311299      {
312         m_line_counter = m_reg[0x0a];
313         m_status |= STATUS_HINT;
314      }
315      else
316      {
317         m_line_counter--;
318      }
300         if ((m_reg[0x00] & 0x10))
301         {
302            m_irq_state = 1;
319303
320      if ((m_status & STATUS_HINT) && (m_reg[0x00] & 0x10))
321      {
322         m_irq_state = 1;
323
324         if ( !m_cb_int.isnull() )
325            m_cb_int(ASSERT_LINE);
304            if ( !m_cb_int.isnull() )
305               m_cb_int(ASSERT_LINE);
306         }
326307      }
327308      break;
328309
329310   case TIMER_CHECK_VINT:
330      if ((m_status & STATUS_VINT) && (m_reg[0x01] & 0x20))
311      if ((m_pending_status & STATUS_VINT) || (m_status & STATUS_VINT))
331312      {
332         m_irq_state = 1;
313         if ((m_reg[0x01] & 0x20))
314         {
315            m_irq_state = 1;
333316
334         if ( !m_cb_int.isnull() )
335            m_cb_int(ASSERT_LINE);
317            if ( !m_cb_int.isnull() )
318               m_cb_int(ASSERT_LINE);
319         }
336320      }
337321      break;
338322   }
r21804r21805
349333
350334   rec.min_y = rec.max_y = vpos;
351335
336   /* Activate flags that were pending until the end of previous line. */
337   check_pending_flags(m_screen->width());
338   
352339   /* Check if we're on the last line of a frame */
353340   if (vpos == vpos_limit - 1)
354341   {
r21804r21805
375362   {
376363      if (vpos == vpos_limit)
377364      {
378         m_check_hint_timer->adjust( m_screen->time_until_pos( vpos, HINT_HPOS ) );
365         if (m_line_counter == 0x00)
366         {
367            m_line_counter = m_reg[0x0a];
368            m_check_hint_timer->adjust( m_screen->time_until_pos( vpos, HINT_HPOS ) );
369            m_pending_status |= STATUS_HINT;
370         }
371         else
372         {
373            m_line_counter--;
374         }
379375      }
380376      else
381377      {
r21804r21805
384380
385381      if (vpos == vpos_limit + 1)
386382      {
387         m_set_status_vint_timer->adjust( m_screen->time_until_pos( vpos, VINT_FLAG_HPOS ) );
388383         m_check_vint_timer->adjust( m_screen->time_until_pos( vpos, VINT_HPOS ) );
384         m_pending_status |= STATUS_VINT;
389385      }
390386
391387      update_palette();
r21804r21805
419415         m_reg9copy = m_reg[0x09];
420416      }
421417
422      m_check_hint_timer->adjust( m_screen->time_until_pos( vpos, HINT_HPOS ) );
418      if (m_line_counter == 0x00)
419      {
420         m_line_counter = m_reg[0x0a];
421         m_check_hint_timer->adjust( m_screen->time_until_pos( vpos, HINT_HPOS ) );
422         m_pending_status |= STATUS_HINT;
423      }
424      else
425      {
426         m_line_counter--;
427      }
423428
424429      update_palette();
425430
r21804r21805
488493   /* to the address register when in the middle of doing a command.               */
489494   /* Cosmic Spacehead needs this, among others                                    */
490495   /* Clear pending write flag */
491   m_pending = 0;
496   m_pending_reg_write = 0;
492497
493498   /* Return read buffer contents */
494499   temp = m_buffer;
r21804r21805
505510}
506511
507512
513void sega315_5124_device::check_pending_flags( int hpos )
514{
515   if ((m_pending_status & STATUS_HINT) && hpos >= HINT_HPOS)
516   {
517      m_pending_status &= ~STATUS_HINT;
518      m_status |= STATUS_HINT;
519   }
520   if ((m_pending_status & STATUS_VINT) && hpos >= VINT_FLAG_HPOS)
521   {
522      m_pending_status &= ~STATUS_VINT;
523      m_status |= STATUS_VINT;
524   }
525   if ((m_pending_status & STATUS_SPROVR) && hpos >= SPROVR_HPOS)
526   {
527      m_pending_status &= ~STATUS_SPROVR;
528      m_status |= STATUS_SPROVR;
529   }
530   if ((m_pending_status & STATUS_SPRCOL) && hpos >= m_pending_sprcol_x)
531   {
532      m_pending_status &= ~STATUS_SPRCOL;
533      m_status |= STATUS_SPRCOL;
534      m_pending_sprcol_x = 0;
535   }
536}
537
538
508539READ8_MEMBER( sega315_5124_device::register_read )
509540{
510   UINT8 temp = m_status;
541   UINT8 temp;
511542
543   check_pending_flags(m_screen->hpos());
544   temp = m_status;
545   
512546   if ( !space.debugger_access() )
513547   {
514548      /* Clear pending write flag */
515      m_pending = 0;
549      m_pending_reg_write = 0;
516550
517551      m_status &= ~(STATUS_VINT | STATUS_SPROVR | STATUS_SPRCOL | STATUS_HINT);
518552
r21804r21805
536570   /* to the address register when in the middle of doing a command.               */
537571   /* Cosmic Spacehead needs this, among others                                    */
538572   /* Clear pending write flag */
539   m_pending = 0;
573   m_pending_reg_write = 0;
540574
541575   switch(m_addrmode)
542576   {
r21804r21805
567601{
568602   int reg_num;
569603
570   if (m_pending == 0)
604   check_pending_flags(m_screen->hpos());
605
606   if (m_pending_reg_write == 0)
571607   {
572608      m_addr = (m_addr & 0xff00) | data;
573      m_pending = 1;
609      m_pending_reg_write = 1;
574610   }
575611   else
576612   {
577613      /* Clear pending write flag */
578      m_pending = 0;
614      m_pending_reg_write = 0;
579615
580616      m_addrmode = (data >> 6) & 0x03;
581617      m_addr = (data << 8) | (m_addr & 0xff);
r21804r21805
599635         if (reg_num == 0 || reg_num == 1)
600636            set_display_settings();
601637
602         if (reg_num == 1)
638         if ( ( reg_num == 0 && (m_status & STATUS_HINT) ) ||
639              ( reg_num == 1 && (m_status & STATUS_VINT) ) )
603640         {
604            m_check_vint_timer->adjust( m_screen->time_until_pos( m_screen->vpos(), VINT_HPOS) );
605
641            // For HINT disabling through register 00:
642            // "Line IRQ VCount" test, of Flubba's VDPTest ROM, disables HINT to wait
643            // for next VINT, but HINT occurs when the operation is about to execute.
644            // So here, where the setting is done, the irq_state needs to be cleared.
606645            //
607            // When running eagles5 on the ssm2kr driver the irq_state is 1 because of some
646            // For VINT disabling through register 01:
647            // When running eagles5 on the sms2kr driver the irq_state is 1 because of some
608648            // previos HINTs that occured. eagles5 sets register 01 to 0x02 and expects
609649            // the irq state to be cleared after that.
610650            // The following bit of code takes care of that.
611651            //
612            if ((m_status & STATUS_VINT) && !(m_reg[0x01] & 0x20))
652            if ( ( (m_status & STATUS_HINT) && !(m_reg[0x00] & 0x10) ) ||
653                 ( (m_status & STATUS_VINT) && !(m_reg[0x01] & 0x20) ) )
613654            {
614655               if (m_irq_state == 1)
615656               {
r21804r21805
621662                  }
622663               }
623664            }
665            else
666            {
667               // For register 01 and VINT enabling:
668               // Assert the IRQ line for the scoreboard of robocop3,
669               // on the sms/smspal driver, be displayed correctly.
670               //
671               // Assume the same behavior for reg0+HINT.
672               //
673               m_irq_state = 1;
624674
675               if ( !m_cb_int.isnull() )
676                  m_cb_int(ASSERT_LINE);
677            }
625678         }
626679         m_addrmode = 0;
627680         break;
r21804r21805
842895
843896      if (line >= 0 && line < m_frame_timing[ACTIVE_DISPLAY_V])
844897      {
845         m_set_status_sprovr_timer->adjust( m_screen->time_until_pos( pixel_plot_y + line, SPROVR_HPOS ) );
898         m_pending_status |= STATUS_SPROVR;
846899      }
847900   }
848901}
r21804r21805
9991052      }
10001053      if (sprite_col_occurred)
10011054      {
1002         m_set_status_sprcol_timer->adjust( m_screen->time_until_pos( pixel_plot_y + line, SPRCOL_BASEHPOS + sprite_col_x ) );
1055         m_pending_status |= STATUS_SPRCOL;
1056         m_pending_sprcol_x = SPRCOL_BASEHPOS + sprite_col_x;
10031057      }
10041058   }
10051059}
r21804r21805
11881242      }
11891243      if (sprite_col_occurred)
11901244      {
1191         m_set_status_sprcol_timer->adjust( m_screen->time_until_pos( pixel_plot_y + line, SPRCOL_BASEHPOS + sprite_col_x ) );
1245         m_pending_status |= STATUS_SPRCOL;
1246         m_pending_sprcol_x = SPRCOL_BASEHPOS + sprite_col_x;
11921247      }
11931248   }
11941249}
r21804r21805
16441699   m_display_timer = timer_alloc(TIMER_LINE);
16451700   m_display_timer->adjust(m_screen->time_until_pos(0, DISPLAY_CB_HPOS), 0, m_screen->scan_period());
16461701   m_draw_timer = timer_alloc(TIMER_DRAW);
1647   m_set_status_vint_timer = timer_alloc( TIMER_SET_STATUS_VINT );
1648   m_set_status_sprovr_timer = timer_alloc( TIMER_SET_STATUS_SPROVR );
1649   m_set_status_sprcol_timer = timer_alloc( TIMER_SET_STATUS_SPRCOL );
1650   m_check_hint_timer = timer_alloc( TIMER_CHECK_HINT );
1651   m_check_vint_timer = timer_alloc( TIMER_CHECK_VINT );
1702   m_check_hint_timer = timer_alloc(TIMER_CHECK_HINT);
1703   m_check_vint_timer = timer_alloc(TIMER_CHECK_VINT);
16521704
16531705   save_item(NAME(m_status));
1706   save_item(NAME(m_pending_status));
1707   save_item(NAME(m_pending_sprcol_x));
16541708   save_item(NAME(m_reg9copy));
16551709   save_item(NAME(m_addrmode));
16561710   save_item(NAME(m_addr));
16571711   save_item(NAME(m_cram_mask));
16581712   save_item(NAME(m_cram_dirty));
1659   save_item(NAME(m_pending));
1713   save_item(NAME(m_pending_reg_write));
16601714   save_item(NAME(m_buffer));
16611715   save_item(NAME(m_sega315_5124_compatibility_mode));
16621716   save_item(NAME(m_irq_state));
r21804r21805
16861740   m_reg[0x0a] = 0xff;
16871741
16881742   m_status = 0;
1743   m_pending_status = 0;
1744   m_pending_sprcol_x = 0;
1745   m_pending_reg_write = 0;
16891746   m_reg9copy = 0;
16901747   m_addrmode = 0;
16911748   m_addr = 0;
16921749   m_sega315_5124_compatibility_mode = false;
16931750   m_cram_mask = m_cram_size - 1;
16941751   m_cram_dirty = 1;
1695   m_pending = 0;
16961752   m_buffer = 0;
16971753   m_irq_state = 0;
16981754   m_line_counter = 0;
trunk/src/emu/video/315_5124.h
r21804r21805
103103   void draw_scanline_mode2( int *line_buffer, int line );
104104   void draw_scanline_mode0( int *line_buffer, int line );
105105   void select_sprites( int pixel_plot_y, int line );
106   void check_pending_flags( int hpos );
106107
107108   // device-level overrides
108109   virtual void device_config_complete();
r21804r21805
114115
115116   UINT8            m_reg[16];                  /* All the registers */
116117   UINT8            m_status;                   /* Status register */
118   UINT8            m_pending_status;           /* Pending status flags */
117119   UINT8            m_reg9copy;                 /* Internal copy of register 9 */
118120   UINT8            m_addrmode;                 /* Type of VDP action */
119121   UINT16           m_addr;                     /* Contents of internal VDP address register */
120122   UINT8            m_cram_size;                /* CRAM size */
121123   UINT8            m_cram_mask;                /* Mask to switch between SMS and GG CRAM sizes */
122124   int              m_cram_dirty;               /* Have there been any changes to the CRAM area */
123   int              m_pending;
125   int              m_pending_reg_write;
126   int              m_pending_sprcol_x;
124127   UINT8            m_buffer;
125128   bool             m_sega315_5124_compatibility_mode;    /* Shrunk SMS screen on GG lcd mode flag */
126129   int              m_irq_state;                /* The status of the IRQ line of the VDP */
r21804r21805
132135   memory_region    *m_CRAM;                    /* Pointer to CRAM */
133136   const UINT8      *m_frame_timing;
134137   bitmap_rgb32     m_tmpbitmap;
135   bitmap_ind8  m_y1_bitmap;
138   bitmap_ind8      m_y1_bitmap;
136139   UINT8            m_collision_buffer[SEGA315_5124_WIDTH];
137140   UINT8            m_palette_offset;
138141   bool             m_supports_224_240;
r21804r21805
150153   devcb_resolved_write_line   m_cb_int;
151154   devcb_resolved_write_line   m_cb_pause;
152155   emu_timer        *m_display_timer;
153   emu_timer        *m_set_status_vint_timer;
154   emu_timer        *m_set_status_sprovr_timer;
155   emu_timer        *m_set_status_sprcol_timer;
156156   emu_timer        *m_check_hint_timer;
157157   emu_timer        *m_check_vint_timer;
158158   emu_timer        *m_draw_timer;
r21804r21805
162162
163163   /* Timers */
164164   static const device_timer_id TIMER_LINE = 0;
165   static const device_timer_id TIMER_SET_STATUS_VINT = 1;
166   static const device_timer_id TIMER_SET_STATUS_SPROVR = 2;
167   static const device_timer_id TIMER_CHECK_HINT = 3;
168   static const device_timer_id TIMER_CHECK_VINT = 4;
169   static const device_timer_id TIMER_SET_STATUS_SPRCOL = 5;
170   static const device_timer_id TIMER_DRAW = 6;
165   static const device_timer_id TIMER_DRAW = 1;
166   static const device_timer_id TIMER_CHECK_HINT = 2;
167   static const device_timer_id TIMER_CHECK_VINT = 3;
171168};
172169
173170
trunk/src/mess/machine/sms.c
r21804r21805
391391
392392UINT8 sms_state::sms_vdp_hcount()
393393{
394   UINT8 tmp;
395   int hpos = m_main_scr->hpos();
394   UINT64 cycles_per_line;
395   attotime line_remaining_time;
396   UINT64 line_remaining_cycles;
397   UINT64 line_elapsed_cycles;
396398
397   /* alternative method: pass HCounter test, but some others fail */
398   //int hpos_tmp = hpos;
399   //if ((hpos + 2) % 6 == 0) hpos_tmp--;
400   //tmp = ((hpos_tmp - 46) >> 1) & 0xff;
399   /* Calculate amount of CPU cycles according to screen references.
400      If some day the screen become always synced to the CPU, in the
401      proportion of their speeds, this may be replaced by the screen
402      hpos position only and the function be moved to the VDP file. */
403   cycles_per_line = m_main_cpu->attotime_to_clocks(m_main_scr->scan_period());
404   line_remaining_time = m_main_scr->time_until_pos(m_main_scr->vpos(), m_main_scr->width());
405   line_remaining_cycles = m_main_cpu->attotime_to_clocks(line_remaining_time) % cycles_per_line;
406   line_elapsed_cycles = cycles_per_line - line_remaining_cycles;
401407
402   UINT64 calc_cycles;
403   attotime time_end;
404   int vpos = m_main_scr->vpos();
405   int max_hpos = m_main_scr->width() - 1;
408   /* HCount equation, being hpos = VDP hclocks: "(hpos - 47) / 2"
409      Screen hpos based on CPU cycles: "cycles * width / cycles per line"
410      Do both in same line for one-step rounding only (required). */
411   return ((line_elapsed_cycles * m_main_scr->width() / cycles_per_line) - 47) / 2;
406412
407   if (hpos == max_hpos)
408      time_end = attotime::zero;
409   else
410      time_end = m_main_scr->time_until_pos(vpos, max_hpos);
411   calc_cycles = m_main_cpu->attotime_to_clocks(time_end);
412
413   /* equation got from SMSPower forum, posted by Flubba. */
414   tmp = ((590 - (calc_cycles * 3)) / 4) & 0xff;
415
416   //printf ("sms_vdp_hcount: hpos %3d => hcount %2X\n", hpos, tmp);
417   return tmp;
413   /* Alternative hcount equation, restricted to the SMS clock:
414      "(590 - (line_remaining_cycles * 3)) / 4"
415      Posted by Flubba on SMSPower forum. */
418416}
419417
420418
r21804r21805
19271925   // the "call $4010" without a following RET statement. That is basically
19281926   // a bug in the program code. The only way this cartridge could have run
19291927   // successfully on a real unit is if the RAM would be initialized with
1930   // a F0 pattern on power up; F0 = RET P.
1931   //
1932   // alibaba and blockhol SMS cartridges rely on uninitialized RAM,
1933   // then fill it with a F0 pattern ("RET P"), but only for consoles
1934   // in Japan region (including KR), until confirmed on other consoles.
1928   // a F0 pattern on power up; F0 = RET P. Do that only for consoles in
1929   // Japan region (including KR), until confirmed on other consoles.
19351930   if (m_is_region_japan)
19361931   {
19371932      memset((UINT8*)m_space->get_write_ptr(0xc000), 0xf0, 0x1FFF);
trunk/src/mess/drivers/sms.c
r21804r21805
7070
7171#include "sms1.lh"
7272
73#define MASTER_CLOCK_PAL    53203400    /* This might be a tiny bit too low */
73#define MASTER_CLOCK_PAL    53203425    /* 12 * subcarrier freq. (4.43361875MHz) */
7474
7575
7676static ADDRESS_MAP_START( sms1_mem, AS_PROGRAM, 8, sms_state )

Previous 199869 Revisions Next


© 1997-2024 The MAME Team