Previous 199869 Revisions Next

r22824 Tuesday 14th May, 2013 at 20:56:54 UTC by Wilbert Pol
(MESS) sms.c: Change hcount calculation to use screen timings and move it to the VDP.  [Enik Land]
[src/emu/video]315_5124.c 315_5124.h
[src/mess/drivers]sms.c
[src/mess/includes]sms.h
[src/mess/machine]sms.c

trunk/src/emu/video/315_5124.c
r22823r22824
5656
5757#define VINT_HPOS             24
5858#define VINT_FLAG_HPOS        23
59#define HINT_HPOS             25
59#define HINT_HPOS             26
6060#define VCOUNT_CHANGE_HPOS    23
6161#define SPROVR_HPOS           23
6262#define SPRCOL_BASEHPOS       59
r22823r22824
261261}
262262
263263
264READ8_MEMBER( sega315_5124_device::hcount_latch_read )
264READ8_MEMBER( sega315_5124_device::hcount_read )
265265{
266266   return m_hcounter;
267267}
268268
269269
270WRITE8_MEMBER( sega315_5124_device::hcount_latch_write )
270void sega315_5124_device::hcount_latch_at_hpos( int hpos )
271271{
272   m_hcounter = data;
272   /* The emulation core returns a screen hpos that is one position ahead in comparison
273      with the expected VDP hclock value, if the same range is used (from 0 to width-1). */
274   int hclock = hpos - 1;
275   if (hclock < 0)
276      hclock += m_screen->width();
277
278   /* Calculate and write the new hcount. */
279   m_hcounter = ((hclock - 46) >> 1) & 0xff;
273280}
274281
275282
r22823r22824
440447      m_tmpbitmap.fill(machine().pens[m_current_palette[BACKDROP_COLOR]], rec);
441448      m_y1_bitmap.fill(1, rec);
442449
443      select_sprites( vpos_limit, vpos - vpos_limit );
450      select_sprites( vpos - vpos_limit );
444451      if ( m_draw_time > 0 )
445452      {
446453         m_draw_timer->adjust( m_screen->time_until_pos( vpos, m_draw_time ), vpos_limit );
r22823r22824
475482      /* Draw middle of the border */
476483      /* We need to do this through the regular drawing function so it will */
477484      /* be included in the gamegear scaling functions */
478      select_sprites( vpos_limit + m_frame_timing[TOP_BORDER], vpos - (vpos_limit + m_frame_timing[TOP_BORDER]) );
485      select_sprites( vpos - (vpos_limit + m_frame_timing[TOP_BORDER]) );
479486      draw_scanline( SEGA315_5124_LBORDER_START + SEGA315_5124_LBORDER_WIDTH, vpos_limit + m_frame_timing[TOP_BORDER], vpos - (vpos_limit + m_frame_timing[TOP_BORDER]) );
480487      return;
481488   }
r22823r22824
807814         pixel_plot_x = (0 - (x_scroll & 0x07) + (tile_column << 3) + pixel_plot_x);
808815         if (pixel_plot_x >= 0 && pixel_plot_x < 256)
809816         {
810//              logerror("%x %x\n", pixel_plot_x + pixel_offset_x, pixel_plot_y);
817            //logerror("%x %x\n", pixel_plot_x, line);
811818            line_buffer[pixel_plot_x] = m_current_palette[pen_selected];
812819            priority_selected[pixel_plot_x] = priority_select | (pen_selected & 0x0f);
813820         }
r22823r22824
816823}
817824
818825
819void sega315_5124_device::select_sprites( int pixel_plot_y, int line )
826void sega315_5124_device::select_sprites( int line )
820827{
821828   int sprite_index = 0;
822829   int max_sprites = 0;
r22823r22824
901908}
902909
903910
904void sega315_5124_device::draw_sprites_mode4( int *line_buffer, int *priority_selected, int pixel_plot_y, int line )
911void sega315_5124_device::draw_sprites_mode4( int *line_buffer, int *priority_selected, int line )
905912{
906913   bool sprite_col_occurred = false;
907   int sprite_col_x = 1000;
914   int sprite_col_x = m_screen->width();
908915
909916   /* Draw sprite layer */
910917
r22823r22824
10591066}
10601067
10611068
1062void sega315_5124_device::draw_sprites_tms9918_mode( int *line_buffer, int pixel_plot_y, int line )
1069void sega315_5124_device::draw_sprites_tms9918_mode( int *line_buffer, int line )
10631070{
10641071   bool sprite_col_occurred = false;
1065   int sprite_col_x = 1000;
1072   int sprite_col_x = m_screen->width();
10661073   UINT16 sprite_pattern_base = ((m_reg[0x06] & 0x07) << 11);
10671074
10681075   /* Draw sprite layer */
r22823r22824
13551362         }
13561363         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
13571364         {
1358            draw_sprites_tms9918_mode( blitline_buffer, pixel_plot_y, line );
1365            draw_sprites_tms9918_mode( blitline_buffer, line );
13591366         }
13601367         break;
13611368
r22823r22824
13671374         }
13681375         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
13691376         {
1370            draw_sprites_tms9918_mode( blitline_buffer, pixel_plot_y, line );
1377            draw_sprites_tms9918_mode( blitline_buffer, line );
13711378         }
13721379         break;
13731380
r22823r22824
13801387         }
13811388         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
13821389         {
1383            draw_sprites_mode4( blitline_buffer, priority_selected, pixel_plot_y, line );
1390            draw_sprites_mode4( blitline_buffer, priority_selected, line );
13841391            if ( line >= 0 )
13851392            {
13861393               /* Fill column 0 with overscan color from m_reg[0x07] */
r22823r22824
14491456         }
14501457         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
14511458         {
1452            draw_sprites_tms9918_mode( blitline_buffer, pixel_plot_y, line );
1459            draw_sprites_tms9918_mode( blitline_buffer, line );
14531460         }
14541461         break;
14551462
r22823r22824
14601467         }
14611468         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
14621469         {
1463            draw_sprites_tms9918_mode( blitline_buffer, pixel_plot_y, line );
1470            draw_sprites_tms9918_mode( blitline_buffer, line );
14641471         }
14651472         break;
14661473
r22823r22824
14731480         }
14741481         if ( line >= 0 || ( line >= -13 && m_y_pixels == 192 ) )
14751482         {
1476            draw_sprites_mode4( blitline_buffer, priority_selected, pixel_plot_y, line );
1483            draw_sprites_mode4( blitline_buffer, priority_selected, line );
14771484            if ( line >= 0 )
14781485            {
14791486               /* Fill column 0 with overscan color from m_reg[0x07] */
trunk/src/emu/video/315_5124.h
r22823r22824
8080   DECLARE_READ8_MEMBER( register_read );
8181   DECLARE_WRITE8_MEMBER( register_write );
8282   DECLARE_READ8_MEMBER( vcount_read );
83   DECLARE_READ8_MEMBER( hcount_latch_read );
84   DECLARE_WRITE8_MEMBER( hcount_latch_write );
83   DECLARE_READ8_MEMBER( hcount_read );
8584
85   void hcount_latch() { hcount_latch_at_hpos( m_screen->hpos() ); };
86   void hcount_latch_at_hpos( int hpos );
87
8688   bitmap_rgb32 &get_bitmap() { return m_tmpbitmap; };
8789   bitmap_ind8 &get_y1_bitmap() { return m_y1_bitmap; };
8890
r22823r22824
98100   virtual UINT16 get_name_table_address();
99101   void process_line_timer();
100102   void draw_scanline_mode4( int *line_buffer, int *priority_selected, int line );
101   void draw_sprites_mode4( int *line_buffer, int *priority_selected, int pixel_plot_y, int line );
102   void draw_sprites_tms9918_mode( int *line_buffer, int pixel_plot_y, int line );
103   void draw_sprites_mode4( int *line_buffer, int *priority_selected, int line );
104   void draw_sprites_tms9918_mode( int *line_buffer, int line );
103105   void draw_scanline_mode2( int *line_buffer, int line );
104106   void draw_scanline_mode0( int *line_buffer, int line );
105   void select_sprites( int pixel_plot_y, int line );
107   void select_sprites( int line );
106108   void check_pending_flags( int hpos );
107109
108110   // device-level overrides
trunk/src/mess/machine/sms.c
r22823r22824
279279   }
280280}
281281
282/* FIXME: this function is a hack for Light Phaser emulation. Theoretically
283   sms_vdp_hcount_latch() should be used instead, but it returns incorrect
284   position for unknown reason (timing?) */
285void sms_state::vdp_hcount_lphaser( int hpos )
286{
287   int hpos_tmp = hpos + m_lphaser_x_offs;
288   UINT8 tmp = ((hpos_tmp - 46) >> 1) & 0xff;
289282
290   //printf ("sms_vdp_hcount_lphaser: hpos %3d hpos_tmp %3d => hcount %2X\n", hpos, hpos_tmp, tmp);
291   m_vdp->hcount_latch_write(*m_space, 0, tmp);
292}
293
294
295283/*
296284    Light Phaser (light gun) emulation notes:
297285    - The sensor is activated based on color brightness of some individual
r22823r22824
323311   int dx, dy;
324312   int result = 0;
325313   int pos_changed = 0;
326   double dx_circ;
314   double dx_radius;
327315
328316   while (1)
329317   {
318      /* If beam's y isn't at a line where the aim area is, change it
319         the next line it enters that area. */
330320      dy = abs(beam_y - lgun_y);
331
332321      if (dy > LGUN_RADIUS || beam_y < visarea.min_y || beam_y > visarea.max_y)
333322      {
334323         beam_y = lgun_y - LGUN_RADIUS;
r22823r22824
337326         dy = abs(beam_y - lgun_y);
338327         pos_changed = 1;
339328      }
340      /* step 1: r^2 = dx^2 + dy^2 */
341      /* step 2: dx^2 = r^2 - dy^2 */
342      /* step 3: dx = sqrt(r^2 - dy^2) */
343      dx_circ = ceil((float) sqrt((float) (r_x_r - (dy * dy))));
344      dx = abs(beam_x - lgun_x);
345329
346      if (dx > dx_circ || beam_x < visarea.min_x || beam_x > visarea.max_x)
330      /* Caculate distance in x of the radius, relative to beam's y distance.
331         First try some shortcuts. */
332      switch (dy)
333       {
334      case LGUN_RADIUS:
335         dx_radius = 0;
336         break;
337      case 0:
338         dx_radius = LGUN_RADIUS;
339         break;
340      default:
341         /* step 1: r^2 = dx^2 + dy^2 */
342         /* step 2: dx^2 = r^2 - dy^2 */
343         /* step 3: dx = sqrt(r^2 - dy^2) */
344         dx_radius = ceil((float) sqrt((float) (r_x_r - (dy * dy))));
345      }
346
347      /* If beam's x isn't in the circular aim area, change it
348         to the next point it enters that area. */
349      dx = abs(beam_x - lgun_x);
350      if (dx > dx_radius || beam_x < visarea.min_x || beam_x > visarea.max_x)
347351      {
352         /* If beam's x has passed the aim area, advance to
353            next line and recheck y/x coordinates. */
348354         if (beam_x > lgun_x)
349355         {
350356            beam_x = 0;
351357            beam_y++;
352358            continue;
353359         }
354         beam_x = lgun_x - dx_circ;
360         beam_x = lgun_x - dx_radius;
355361         if (beam_x < visarea.min_x)
356362            beam_x = visarea.min_x;
357363         pos_changed = 1;
r22823r22824
389395   return result;
390396}
391397
392UINT8 sms_state::sms_vdp_hcount()
393{
394   UINT64 cycles_per_line;
395   attotime line_remaining_time;
396   UINT64 line_remaining_cycles;
397   UINT64 line_elapsed_cycles;
398398
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;
407
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;
412
413   /* Alternative hcount equation, restricted to the SMS clock:
414      "(590 - (line_remaining_cycles * 3)) / 4"
415      Posted by Flubba on SMSPower forum. */
416}
417
418
419void sms_state::sms_vdp_hcount_latch( address_space &space )
399void sms_state::lphaser_hcount_latch( int hpos )
420400{
421   UINT8 value = sms_vdp_hcount();
422
423   m_vdp->hcount_latch_write(space, 0, value);
401   /* A delay seems to occur when the Light Phaser latches the
402      VDP hcount, then an offset is added here to the hpos. */
403   m_vdp->hcount_latch_at_hpos(hpos + m_lphaser_x_offs);
424404}
425405
426406
427407UINT16 sms_state::screen_hpos_nonscaled(int scaled_hpos)
428408{
429409   const rectangle &visarea = m_main_scr->visible_area();
430   int offset_x = (scaled_hpos * visarea.width()) / 255;
410   int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255;
431411   return visarea.min_x + offset_x;
432412}
433413
r22823r22824
450430      if (m_lphaser_1_latch == 0)
451431      {
452432         m_lphaser_1_latch = 1;
453         vdp_hcount_lphaser(x);
433         lphaser_hcount_latch(x);
454434      }
455435   }
456436}
r22823r22824
465445      if (m_lphaser_2_latch == 0)
466446      {
467447         m_lphaser_2_latch = 1;
468         vdp_hcount_lphaser(x);
448         lphaser_hcount_latch(x);
469449      }
470450   }
471451}
r22823r22824
573553
574554   case 0x01:  /* Light Phaser */
575555      data = (ioport("CTRLIPT")->read() & 0x01) << 4;
576      if (!(data & 0x10))
577      {
578         if (ioport("RFU")->read() & 0x01)
579            data |= m_rapid_fire_state_1 & 0x10;
580      }
581      /* just consider the button (trigger) bit */
556      /* Check Rapid Fire setting for Trigger */
557      if (!(data & 0x10) && (ioport("RFU")->read() & 0x01))
558         data |= m_rapid_fire_state_1 & 0x10;
559
560      /* just consider the trigger (button) bit */
582561      data |= ~0x10;
562
583563      m_input_port0 = (m_input_port0 & 0xc0) | (data & 0x3f);
584564      break;
585565
r22823r22824
635615
636616   case 0x10:  /* Light Phaser */
637617      data = (ioport("CTRLIPT")->read() & 0x10) >> 2;
638      if (!(data & 0x04))
639      {
640         if (ioport("RFU")->read() & 0x04)
641            data |= m_rapid_fire_state_2 & 0x04;
642      }
643      /* just consider the button (trigger) bit */
618      /* Check Rapid Fire setting for Trigger */
619      if (!(data & 0x04) && (ioport("RFU")->read() & 0x04))
620         data |= m_rapid_fire_state_2 & 0x04;
621
622      /* just consider the trigger (button) bit */
644623      data |= ~0x04;
624
645625      m_input_port1 = (m_input_port1 & 0xf0) | (data & 0x0f);
646626      break;
647627
r22823r22824
708688
709689WRITE8_MEMBER(sms_state::sms_io_control_w)
710690{
711   bool hcount_latch = false;
691   bool latch_hcount = false;
712692
713693   if (data & 0x08)
714694   {
715695      /* check if TH pin level is high (1) and was low last time */
716696      if (data & 0x80 && !(m_ctrl_reg & 0x80))
717697      {
718         hcount_latch = true;
698         latch_hcount = true;
719699      }
720700      sms_input_write(space, 0, (data & 0x20) >> 5);
721701   }
r22823r22824
724704   {
725705      if (data & 0x20 && !(m_ctrl_reg & 0x20))
726706      {
727         hcount_latch = true;
707         latch_hcount = true;
728708      }
729709      sms_input_write(space, 1, (data & 0x80) >> 7);
730710   }
731711
732   if (hcount_latch)
712   if (latch_hcount)
733713   {
734      sms_vdp_hcount_latch(space);
714      m_vdp->hcount_latch();
735715   }
736716
737717   m_ctrl_reg = data;
r22823r22824
741721READ8_MEMBER(sms_state::sms_count_r)
742722{
743723   if (offset & 0x01)
744      return m_vdp->hcount_latch_read(*m_space, offset);
724      return m_vdp->hcount_read(*m_space, offset);
745725   else
746726      return m_vdp->vcount_read(*m_space, offset);
747727}
r22823r22824
15311511   if (!(m_bios_port & IO_CARTRIDGE) && m_cartridge[m_current_cartridge].size >= 0x8000)
15321512   {
15331513      if (!memcmp(&rom[0x7ff0], signatures[0], 16) || !memcmp(&rom[0x7ff0], signatures[1], 16))
1534         return 40;
1514         return 41;
15351515
15361516      if (!memcmp(&rom[0x7ff0], signatures[2], 16))
1537         return 49;
1517         return 50;
15381518
15391519      if (!memcmp(&rom[0x7ff0], signatures[3], 16))
1540         return 47;
1520         return 48;
15411521
15421522      if (!memcmp(&rom[0x7ff0], signatures[4], 16))
1543         return 44;
1523         return 45;
15441524
15451525      if (!memcmp(&rom[0x7ff0], signatures[5], 16))
1546         return 53;
1526         return 54;
15471527
15481528   }
1549   return 50;
1529   return 51;
15501530}
15511531
15521532
r22823r22824
22602240
22612241VIDEO_START_MEMBER(sms_state,gamegear)
22622242{
2263   screen_device *screen = machine().first_screen();
2264
2265   screen->register_screen_bitmap(m_prev_bitmap);
2243   m_main_scr->register_screen_bitmap(m_prev_bitmap);
22662244   save_item(NAME(m_prev_bitmap));
22672245}
22682246
trunk/src/mess/includes/sms.h
r22823r22824
216216   required_shared_ptr<UINT8> m_mainram;
217217
218218   void setup_rom();
219   void vdp_hcount_lphaser(int hpos);
219   void lphaser_hcount_latch(int hpos);
220220   void lphaser1_sensor_check();
221221   void lphaser2_sensor_check();
222222   UINT16 screen_hpos_nonscaled(int scaled_hpos);
223223   UINT16 screen_vpos_nonscaled(int scaled_vpos);
224224   int lgun_bright_aim_area(emu_timer *timer, int lgun_x, int lgun_y);
225   void sms_vdp_hcount_latch(address_space &space);
226   UINT8 sms_vdp_hcount();
227225   void setup_cart_banks();
228226   void setup_banks();
229227   void sms_get_inputs(address_space &space);
trunk/src/mess/drivers/sms.c
r22823r22824
243243   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR( X, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun2_changed, NULL) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
244244
245245   PORT_START("LPHASER3")  /* Light phaser Y - player 2 */
246   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(25) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun2_changed, NULL) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
246   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_state, lgun2_changed, NULL) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
247247
248248   PORT_START("RFU")   /* Rapid Fire Unit */
249249   PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit - Player 1" )

Previous 199869 Revisions Next


© 1997-2024 The MAME Team