Viewing File: <root>/src/mame/video/segaic24.c

    1  /*
    2    Sega system24 hardware
    3  
    4  System 24      68000x2  315-5292   315-5293  315-5294  315-5242        ym2151 dac           315-5195(x3) 315-5296(IO)
    5  
    6    System24:
    7      The odd one out.  Medium resolution. Entirely ram-based, no
    8      graphics roms.  4-layer tilemap hardware in two pairs, selection
    9      on a 8-pixels basis.  Tile-based sprites(!) organised as a linked
   10      list.  The tilemap chip has been reused for model1 and model2,
   11      probably because they had it handy and it handles medium res.
   12  
   13  */
   14  
   15  #include "emu.h"
   16  #include "segaic24.h"
   17  
   18  
   19  const device_type S24TILE = &device_creator<segas24_tile>;
   20  const device_type S24SPRITE = &device_creator<segas24_sprite>;
   21  const device_type S24MIXER = &device_creator<segas24_mixer>;
   22  
   23  
   24  segas24_tile::segas24_tile(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
   25      : device_t(mconfig, S24TILE, "S24TILE", tag, owner, clock)
   26  {
   27  }
   28  
   29  void segas24_tile::static_set_tile_mask(device_t &device, UINT16 _tile_mask)
   30  {
   31      segas24_tile &dev = downcast<segas24_tile &>(device);
   32      dev.tile_mask = _tile_mask;
   33  }
   34  
   35  #define XOR(a) WORD_XOR_BE(a)
   36  
   37  const gfx_layout segas24_tile::char_layout = {
   38      8, 8,
   39      SYS24_TILES,
   40      4,
   41      { 0, 1, 2, 3 },
   42      { XOR(0)*4, XOR(1)*4, XOR(2)*4, XOR(3)*4, XOR(4)*4, XOR(5)*4, XOR(6)*4, XOR(7)*4 },
   43      { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
   44      8*32
   45  };
   46  
   47  void segas24_tile::tile_info(int offset, tile_data &tileinfo, tilemap_memory_index tile_index)
   48  {
   49      UINT16 val = tile_ram[tile_index|offset];
   50      tileinfo.category = (val & 0x8000) != 0;
   51      tileinfo.set(machine(), char_gfx_index, val & tile_mask, (val >> 7) & 0xff, 0);
   52  }
   53  
   54  TILE_GET_INFO_MEMBER(segas24_tile::tile_info_0s)
   55  {
   56      tile_info(0x0000, tileinfo, tile_index);
   57  }
   58  
   59  TILE_GET_INFO_MEMBER( segas24_tile::tile_info_0w)
   60  {
   61      tile_info(0x1000, tileinfo, tile_index);
   62  }
   63  
   64  TILE_GET_INFO_MEMBER(segas24_tile::tile_info_1s)
   65  {
   66      tile_info(0x2000, tileinfo, tile_index);
   67  }
   68  
   69  TILE_GET_INFO_MEMBER(segas24_tile::tile_info_1w)
   70  {
   71      tile_info(0x3000, tileinfo, tile_index);
   72  }
   73  
   74  void segas24_tile::device_start()
   75  {
   76      for(char_gfx_index = 0; char_gfx_index < MAX_GFX_ELEMENTS; char_gfx_index++)
   77          if (machine().gfx[char_gfx_index] == 0)
   78              break;
   79      assert(char_gfx_index != MAX_GFX_ELEMENTS);
   80  
   81      char_ram = auto_alloc_array(machine(), UINT16, 0x80000/2);
   82      tile_ram = auto_alloc_array(machine(), UINT16, 0x10000/2);
   83  
   84      tile_layer[0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(segas24_tile::tile_info_0s),this), TILEMAP_SCAN_ROWS,  8, 8, 64, 64);
   85      tile_layer[1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(segas24_tile::tile_info_0w),this), TILEMAP_SCAN_ROWS,  8, 8, 64, 64);
   86      tile_layer[2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(segas24_tile::tile_info_1s),this), TILEMAP_SCAN_ROWS,  8, 8, 64, 64);
   87      tile_layer[3] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(segas24_tile::tile_info_1w),this), TILEMAP_SCAN_ROWS,  8, 8, 64, 64);
   88  
   89      tile_layer[0]->set_transparent_pen(0);
   90      tile_layer[1]->set_transparent_pen(0);
   91      tile_layer[2]->set_transparent_pen(0);
   92      tile_layer[3]->set_transparent_pen(0);
   93  
   94      memset(char_ram, 0, 0x80000);
   95      memset(tile_ram, 0, 0x10000);
   96  
   97      machine().gfx[char_gfx_index] = auto_alloc(machine(), gfx_element(machine(), char_layout, (UINT8 *)char_ram, machine().total_colors() / 16, 0));
   98  
   99      save_pointer(NAME(tile_ram), 0x10000/2);
  100      save_pointer(NAME(char_ram), 0x80000/2);
  101  }
  102  
  103  void segas24_tile::draw_rect(bitmap_ind16 &bm, bitmap_ind8 &tm, bitmap_ind16 &dm, const UINT16 *mask,
  104                               UINT16 tpri, UINT8 lpri, int win, int sx, int sy, int xx1, int yy1, int xx2, int yy2)
  105  {
  106      int y;
  107      const UINT16 *source  = &bm.pix16(sy, sx);
  108      const UINT8  *trans = &tm.pix8(sy, sx);
  109      UINT8        *prib = &machine().priority_bitmap.pix8(0);
  110      UINT16       *dest = &dm.pix16(0);
  111  
  112      tpri |= TILEMAP_PIXEL_LAYER0;
  113  
  114      dest += yy1*dm.rowpixels() + xx1;
  115      prib += yy1*machine().priority_bitmap.rowpixels() + xx1;
  116      mask += yy1*4;
  117      yy2 -= yy1;
  118  
  119      while(xx1 >= 128) {
  120          xx1 -= 128;
  121          xx2 -= 128;
  122          mask++;
  123      }
  124  
  125      for(y=0; y<yy2; y++) {
  126          const UINT16 *src   = source;
  127          const UINT8  *srct  = trans;
  128          UINT16 *dst         = dest;
  129          UINT8 *pr           = prib;
  130          const UINT16 *mask1 = mask;
  131          int llx = xx2;
  132          int cur_x = xx1;
  133  
  134          while(llx > 0) {
  135              UINT16 m = *mask1++;
  136  
  137              if(win)
  138                  m = ~m;
  139  
  140              if(!cur_x && llx>=128) {
  141                  // Fast paths for the 128-pixels without side clipping case
  142  
  143                  if(!m) {
  144                      // 1- 128 pixels from this layer
  145                      int x;
  146                      for(x=0; x<128; x++) {
  147                          if(*srct++ == tpri) {
  148                              *dst = *src;
  149                              *pr |= lpri;
  150                          }
  151                          src++;
  152                          dst++;
  153                          pr++;
  154                      }
  155  
  156                  } else if(m == 0xffff) {
  157                      // 2- 128 pixels from the other layer
  158                      src += 128;
  159                      srct += 128;
  160                      dst += 128;
  161                      pr += 128;
  162  
  163                  } else {
  164                      // 3- 128 pixels from both layers
  165                      int x;
  166                      for(x=0; x<128; x+=8) {
  167                          if(!(m & 0x8000)) {
  168                              int xx;
  169                              for(xx=0; xx<8; xx++)
  170                                  if(srct[xx] == tpri) {
  171                                     dst[xx] = src[xx];
  172                                     pr[xx] |= lpri;
  173                                  }
  174                          }
  175                          src += 8;
  176                          srct += 8;
  177                          dst += 8;
  178                          pr += 8;
  179                          m <<= 1;
  180                      }
  181                  }
  182              } else {
  183                  // Clipped path
  184                  int llx1 = llx >= 128 ? 128 : llx;
  185  
  186                  if(!m) {
  187                      // 1- 128 pixels from this layer
  188                      int x;
  189                      for(x = cur_x; x<llx1; x++) {
  190                          if(*srct++ == tpri) {
  191                             *dst = *src;
  192                             *pr |= lpri;
  193                          }
  194                          src++;
  195                          dst++;
  196                          pr++;
  197                      }
  198  
  199                  } else if(m == 0xffff) {
  200                      // 2- 128 pixels from the other layer
  201                      src += 128 - cur_x;
  202                      srct += 128 - cur_x;
  203                      dst += 128 - cur_x;
  204                      pr += 128 - cur_x;
  205  
  206                  } else {
  207                      // 3- 128 pixels from both layers
  208                      int x;
  209                      for(x=cur_x; x<llx1; x++) {
  210                          if(*srct++ == tpri && !(m & (0x8000 >> (x >> 3)))) {
  211                             *dst = *src;
  212                             *pr |= lpri;
  213                          }
  214  
  215                          src++;
  216                          dst++;
  217                          pr++;
  218                      }
  219                  }
  220              }
  221              llx -= 128;
  222              cur_x = 0;
  223          }
  224          source += bm.rowpixels();
  225          trans  += tm.rowpixels();
  226          dest   += dm.rowpixels();
  227          prib   += machine().priority_bitmap.rowpixels();
  228          mask   += 4;
  229      }
  230  }
  231  
  232  
  233  // The rgb version is used by model 1 & 2 which do not need to care
  234  // about sprite priority hence the lack of support for the
  235  // priority_bitmap
  236  
  237  void segas24_tile::draw_rect(bitmap_ind16 &bm, bitmap_ind8 &tm, bitmap_rgb32 &dm, const UINT16 *mask,
  238                                   UINT16 tpri, UINT8 lpri, int win, int sx, int sy, int xx1, int yy1, int xx2, int yy2)
  239  {
  240      int y;
  241      const UINT16 *source  = &bm.pix16(sy, sx);
  242      const UINT8  *trans = &tm.pix8(sy, sx);
  243      UINT32       *dest = &dm.pix32(0);
  244      const pen_t  *pens   = machine().pens;
  245  
  246      tpri |= TILEMAP_PIXEL_LAYER0;
  247  
  248      dest += yy1*dm.rowpixels() + xx1;
  249      mask += yy1*4;
  250      yy2 -= yy1;
  251  
  252      while(xx1 >= 128) {
  253          xx1 -= 128;
  254          xx2 -= 128;
  255          mask++;
  256      }
  257  
  258      for(y=0; y<yy2; y++) {
  259          const UINT16 *src   = source;
  260          const UINT8  *srct  = trans;
  261          UINT32 *dst         = dest;
  262          const UINT16 *mask1 = mask;
  263          int llx = xx2;
  264          int cur_x = xx1;
  265  
  266          while(llx > 0) {
  267              UINT16 m = *mask1++;
  268  
  269              if(win)
  270                  m = ~m;
  271  
  272              if(!cur_x && llx>=128) {
  273                  // Fast paths for the 128-pixels without side clipping case
  274  
  275                  if(!m) {
  276                      // 1- 128 pixels from this layer
  277                      int x;
  278                      for(x=0; x<128; x++) {
  279                          if(*srct++ == tpri)
  280                              *dst = pens[*src];
  281                          src++;
  282                          dst++;
  283                      }
  284  
  285                  } else if(m == 0xffff) {
  286                      // 2- 128 pixels from the other layer
  287                      src += 128;
  288                      srct += 128;
  289                      dst += 128;
  290  
  291                  } else {
  292                      // 3- 128 pixels from both layers
  293                      int x;
  294                      for(x=0; x<128; x+=8) {
  295                          if(!(m & 0x8000)) {
  296                              int xx;
  297                              for(xx=0; xx<8; xx++)
  298                                  if(srct[xx] == tpri)
  299                                     dst[xx] = pens[src[xx]];
  300                          }
  301                          src += 8;
  302                          srct += 8;
  303                          dst += 8;
  304                          m <<= 1;
  305                      }
  306                  }
  307              } else {
  308                  // Clipped path
  309                  int llx1 = llx >= 128 ? 128 : llx;
  310  
  311                  if(!m) {
  312                      // 1- 128 pixels from this layer
  313                      int x;
  314                      for(x = cur_x; x<llx1; x++) {
  315                          if(*srct++ == tpri)
  316                             *dst = pens[*src];
  317                          src++;
  318                          dst++;
  319                      }
  320  
  321                  } else if(m == 0xffff) {
  322                      // 2- 128 pixels from the other layer
  323                      src += 128 - cur_x;
  324                      srct += 128 - cur_x;
  325                      dst += 128 - cur_x;
  326  
  327                  } else {
  328                      // 3- 128 pixels from both layers
  329                      int x;
  330                      for(x=cur_x; x<llx1; x++) {
  331                          if(*srct++ == tpri && !(m & (0x8000 >> (x >> 3))))
  332                             *dst = pens[*src];
  333  
  334                          src++;
  335                          dst++;
  336                      }
  337                  }
  338              }
  339              llx -= 128;
  340              cur_x = 0;
  341          }
  342          source += bm.rowpixels();
  343          trans  += tm.rowpixels();
  344          dest   += dm.rowpixels();
  345          mask   += 4;
  346      }
  347  }
  348  
  349  template<class _BitmapClass>
  350  void segas24_tile::draw_common(_BitmapClass &bitmap, const rectangle &cliprect, int layer, int lpri, int flags)
  351  {
  352      UINT16 hscr = tile_ram[0x5000+(layer >> 1)];
  353      UINT16 vscr = tile_ram[0x5004+(layer >> 1)];
  354      UINT16 ctrl = tile_ram[0x5004+((layer >> 1) & 2)];
  355      UINT16 *mask = tile_ram + (layer & 4 ? 0x6800 : 0x6000);
  356      UINT16 tpri = layer & 1;
  357  
  358      lpri = 1 << lpri;
  359      layer >>= 1;
  360  
  361      // Layer disable
  362      if(vscr & 0x8000)
  363          return;
  364  
  365      if(ctrl & 0x6000) {
  366          // Special window/scroll modes
  367          if(layer & 1)
  368              return;
  369  
  370          tile_layer[layer]->set_scrolly(0, vscr & 0x1ff);
  371          tile_layer[layer|1]->set_scrolly(0, vscr & 0x1ff);
  372  
  373          if(hscr & 0x8000) {
  374              UINT16 *hscrtb = tile_ram + 0x4000 + 0x200*layer;
  375  
  376              switch((ctrl & 0x6000) >> 13) {
  377              case 1: {
  378                  int y;
  379                  UINT16 v = (-vscr) & 0x1ff;
  380                  if(!((-vscr) & 0x200))
  381                      layer ^= 1;
  382                  for(y=cliprect.min_y; y<=cliprect.max_y; y++) {
  383                      UINT16 h;
  384                      rectangle c = cliprect;
  385                      int l1 = layer;
  386                      if(y >= v)
  387                          l1 ^= 1;
  388  
  389                      c.min_y = c.max_y = y;
  390  
  391                      hscr = hscrtb[y];
  392  
  393                      h = hscr & 0x1ff;
  394                      tile_layer[l1]->set_scrollx(0, -h);
  395                      tile_layer[l1]->draw(bitmap, c, tpri, lpri);
  396                  }
  397                  break;
  398              }
  399              case 2: case 3: {
  400                  int y;
  401                  for(y=cliprect.min_y; y<=cliprect.max_y; y++) {
  402                      UINT16 h;
  403                      rectangle c1 = cliprect;
  404                      rectangle c2 = cliprect;
  405                      int l1 = layer;
  406  
  407                      hscr = hscrtb[y];
  408  
  409                      h = hscr & 0x1ff;
  410                      tile_layer[layer]->set_scrollx(0, -h);
  411                      tile_layer[layer|1]->set_scrollx(0, -h);
  412  
  413                      if(c1.max_x >= h)
  414                          c1.max_x = h-1;
  415                      if(c2.min_x < h)
  416                          c2.min_x = h;
  417                      if(!(hscr & 0x200))
  418                          l1 ^= 1;
  419  
  420                      c1.min_y = c1.max_y = c2.min_y = c2.max_y = y;
  421  
  422                      tile_layer[l1]->draw(bitmap, c1, tpri, lpri);
  423                      tile_layer[l1^1]->draw(bitmap, c2, tpri, lpri);
  424                  }
  425                  break;
  426              }
  427              }
  428  
  429          } else {
  430              tile_layer[layer]->set_scrollx(0, -(hscr & 0x1ff));
  431              tile_layer[layer|1]->set_scrollx(0, -(hscr & 0x1ff));
  432  
  433              switch((ctrl & 0x6000) >> 13) {
  434              case 1: {
  435                  rectangle c1 = cliprect;
  436                  rectangle c2 = cliprect;
  437                  UINT16 v;
  438                  v = (-vscr) & 0x1ff;
  439                  if(c1.max_y >= v)
  440                      c1.max_y = v-1;
  441                  if(c2.min_y < v)
  442                      c2.min_y = v;
  443                  if(!((-vscr) & 0x200))
  444                      layer ^= 1;
  445  
  446                  tile_layer[layer]->draw(bitmap, c1, tpri, lpri);
  447                  tile_layer[layer^1]->draw(bitmap, c2, tpri, lpri);
  448                  break;
  449              }
  450              case 2: case 3: {
  451                  rectangle c1 = cliprect;
  452                  rectangle c2 = cliprect;
  453                  UINT16 h;
  454                  h = (+hscr) & 0x1ff;
  455                  if(c1.max_x >= h)
  456                      c1.max_x = h-1;
  457                  if(c2.min_x < h)
  458                      c2.min_x = h;
  459                  if(!((+hscr) & 0x200))
  460                      layer ^= 1;
  461  
  462                  tile_layer[layer]->draw(bitmap, c1, tpri, lpri);
  463                  tile_layer[layer^1]->draw(bitmap, c2, tpri, lpri);
  464                  break;
  465              }
  466              }
  467          }
  468  
  469      } else {
  470          int win = layer & 1;
  471  
  472          bitmap_ind16 &bm = tile_layer[layer]->pixmap();
  473          bitmap_ind8 &tm = tile_layer[layer]->flagsmap();
  474  
  475          if(hscr & 0x8000) {
  476              int y;
  477              UINT16 *hscrtb = tile_ram + 0x4000 + 0x200*layer;
  478              vscr &= 0x1ff;
  479  
  480              for(y=0; y<384; y++) {
  481                  hscr = (-hscrtb[y]) & 0x1ff;
  482                  if(hscr + 496 <= 512) {
  483                      // Horizontal split unnecessary
  484                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        y,      496,      y+1);
  485                  } else {
  486                      // Horizontal split necessary
  487                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        y, 512-hscr,      y+1);
  488                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win,    0, vscr, 512-hscr,        y,      496,      y+1);
  489                  }
  490                  vscr = (vscr + 1) & 0x1ff;
  491              }
  492          } else {
  493              hscr = (-hscr) & 0x1ff;
  494              vscr = (+vscr) & 0x1ff;
  495  
  496              if(hscr + 496 <= 512) {
  497                  // Horizontal split unnecessary
  498                  if(vscr + 384 <= 512) {
  499                      // Vertical split unnecessary
  500                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        0,      496,      384);
  501                  } else {
  502                      // Vertical split necessary
  503                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        0,      496, 512-vscr);
  504                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr,    0,        0, 512-vscr,      496,      384);
  505  
  506                  }
  507              } else {
  508                  // Horizontal split necessary
  509                  if(vscr + 384 <= 512) {
  510                      // Vertical split unnecessary
  511                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        0, 512-hscr,      384);
  512                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win,    0, vscr, 512-hscr,        0,      496,      384);
  513                  } else {
  514                      // Vertical split necessary
  515                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr, vscr,        0,        0, 512-hscr, 512-vscr);
  516                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win,    0, vscr, 512-hscr,        0,      496, 512-vscr);
  517                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win, hscr,    0,        0, 512-vscr, 512-hscr,      384);
  518                      draw_rect(bm, tm, bitmap, mask, tpri, lpri, win,    0,    0, 512-hscr, 512-vscr,      496,      384);
  519                  }
  520              }
  521          }
  522      }
  523  }
  524  
  525  void segas24_tile::draw(bitmap_ind16 &bitmap, const rectangle &cliprect, int layer, int lpri, int flags)
  526  { draw_common(bitmap, cliprect, layer, lpri, flags); }
  527  
  528  void segas24_tile::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int lpri, int flags)
  529  { draw_common(bitmap, cliprect, layer, lpri, flags); }
  530  
  531  READ16_MEMBER(segas24_tile::tile_r)
  532  {
  533      return tile_ram[offset];
  534  }
  535  
  536  READ16_MEMBER(segas24_tile::char_r)
  537  {
  538      return char_ram[offset];
  539  }
  540  
  541  WRITE16_MEMBER(segas24_tile::tile_w)
  542  {
  543      COMBINE_DATA(tile_ram + offset);
  544      if(offset < 0x4000)
  545          tile_layer[offset >> 12]->mark_tile_dirty(offset & 0xfff);
  546  }
  547  
  548  WRITE16_MEMBER(segas24_tile::char_w)
  549  {
  550      UINT16 old = char_ram[offset];
  551      COMBINE_DATA(char_ram + offset);
  552      if(old != char_ram[offset])
  553          machine().gfx[char_gfx_index]->mark_dirty(offset / 16);
  554  }
  555  
  556  READ32_MEMBER(segas24_tile::tile32_r)
  557  {
  558      return tile_r(space, offset*2, mem_mask&0xffff) | tile_r(space, (offset*2)+1, mem_mask>>16)<<16;
  559  }
  560  
  561  READ32_MEMBER(segas24_tile::char32_r)
  562  {
  563      return char_r(space, offset*2, mem_mask&0xffff) | char_r(space, (offset*2)+1, mem_mask>>16)<<16;
  564  }
  565  
  566  WRITE32_MEMBER(segas24_tile::tile32_w)
  567  {
  568      tile_w(space, offset*2, data&0xffff, mem_mask&0xffff);
  569      tile_w(space, (offset*2)+1, data>>16, mem_mask>>16);
  570  }
  571  
  572  WRITE32_MEMBER(segas24_tile::char32_w)
  573  {
  574      char_w(space, offset*2, data&0xffff, mem_mask&0xffff);
  575      char_w(space, (offset*2)+1, data>>16, mem_mask>>16);
  576  }
  577  
  578  
  579  segas24_sprite::segas24_sprite(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
  580      : device_t(mconfig, S24SPRITE, "S24SPRITE", tag, owner, clock)
  581  {
  582  }
  583  
  584  void segas24_sprite::device_start()
  585  {
  586      sprite_ram = auto_alloc_array(machine(), UINT16, 0x40000/2);
  587  
  588      save_pointer(NAME(sprite_ram), 0x40000/2);
  589  }
  590  
  591  /* System24 sprites
  592        Normal sprite:
  593      0   00Z--nnn    nnnnnnnn    zoom mode (1 = separate x and y), next sprite
  594      1   xxxxxxxx    yyyyyyyy    zoom x, zoom y (zoom y is used for both when mode = 0)
  595      2   --TTTTTT    TTTTTTTT    sprite number
  596      3   PPPPCCCC    CCCCCCCC    priority, indirect palette base
  597      4   FSSSYYYY    YYYYYYYY    flipy, y size, top
  598      5   FSSSXXXX    XXXXXXXX    flipx, x size, left
  599  
  600        Clip?
  601      0   01---nnn    nnnnnnnn    next sprite
  602      1   hVH-----    --------    hide/vflip/hflip
  603      2   -------y    yyyyyyyy    Clip top
  604      2   -------x    xxxxxxxx    Clip left
  605      2   -------y    yyyyyyyy    Clip bottom
  606      2   -------x    xxxxxxxx    Clip right
  607  
  608        Skipped entry
  609      0   10---nnn    nnnnnnnn    next sprite
  610  
  611        End of sprite list
  612      0   11------    --------
  613  */
  614  
  615  void segas24_sprite::draw(bitmap_ind16 &bitmap, const rectangle &cliprect, const int *spri)
  616  {
  617      UINT16 curspr = 0;
  618      int countspr = 0;
  619      int seen;
  620      UINT8 pmt[4];
  621      int i;
  622      UINT16 *sprd[0x2000], *clip[0x2000];
  623      UINT16 *cclip = 0;
  624  
  625      for(i=0; i<4; i++)
  626          pmt[i] = 0xff << (1+spri[3-i]);
  627  
  628      for(seen = 0; seen < 0x2000; seen++) {
  629          UINT16 *source;
  630          UINT16 type;
  631  
  632          source = sprite_ram + (curspr << 3);
  633  
  634          if(curspr == 0 && source[0] == 0)
  635              break;
  636  
  637          curspr = source[0];
  638          type = curspr & 0xc000;
  639          curspr &= 0x1fff;
  640  
  641          if(type == 0xc000)
  642              break;
  643  
  644          if(type == 0x8000)
  645              continue;
  646  
  647          if(type == 0x4000) {
  648              cclip = source;
  649              continue;
  650          }
  651  
  652          sprd[countspr] = source;
  653          clip[countspr] = cclip;
  654  
  655          countspr++;
  656          if(!curspr)
  657              break;
  658      }
  659  
  660      for(countspr--; countspr >= 0; countspr--) {
  661          UINT16 *source, *pix;
  662          int x, y, sx, sy;
  663          int px, py;
  664          UINT16 colors[16];
  665          int flipx, flipy;
  666          int zoomx, zoomy;
  667          UINT8 pm[16];
  668          //      int dump;
  669          int xmod, ymod;
  670          int min_x, min_y, max_x, max_y;
  671  
  672          UINT32 addoffset;
  673          UINT32 newoffset;
  674          UINT32 offset;
  675  
  676          source = sprd[countspr];
  677          cclip = clip[countspr];
  678  
  679          if(cclip) {
  680              min_y = (cclip[2] & 511);
  681              min_x = (cclip[3] & 511) - 8;
  682              max_y = (cclip[4] & 511);
  683              max_x = (cclip[5] & 511) - 8;
  684          } else {
  685              min_x = 0;
  686              max_x = 495;
  687              min_y = 0;
  688              max_y = 383;
  689          }
  690  
  691  
  692          if(min_x < cliprect.min_x)
  693              min_x = cliprect.min_x;
  694          if(min_y < cliprect.min_y)
  695              min_y = cliprect.min_y;
  696          if(max_x > cliprect.max_x)
  697              max_x = cliprect.max_x;
  698          if(max_y > cliprect.max_y)
  699              max_y = cliprect.max_y;
  700  
  701          if(!(source[0] & 0x2000))
  702              zoomx = zoomy = source[1] & 0xff;
  703          else {
  704              zoomx = source[1] >> 8;
  705              zoomy = source[1] & 0xff;
  706          }
  707          if(!zoomx)
  708              zoomx = 0x3f;
  709          if(!zoomy)
  710              zoomy = 0x3f;
  711  
  712          zoomx++;
  713          zoomy++;
  714  
  715          x = source[5] & 0xfff;
  716          flipx = source[5] & 0x8000;
  717          if(x & 0x800)
  718              x -= 0x1000;
  719          sx = 1 << ((source[5] & 0x7000) >> 12);
  720  
  721          x -= 8;
  722  
  723          y = source[4] & 0xfff;
  724          if(y & 0x800)
  725              y -= 0x1000;
  726          flipy = source[4] & 0x8000;
  727          sy = 1 << ((source[4] & 0x7000) >> 12);
  728  
  729          pix = &sprite_ram[(source[3] & 0x3fff)* 0x8];
  730          for(px=0; px<8; px++) {
  731              int c;
  732              c              = pix[px] >> 8;
  733              pm[px*2]       = pmt[c>>6];
  734              if(c>1)
  735                  c |= 0x1000;
  736              colors[px*2]   = c;
  737  
  738              c              = pix[px] & 0xff;
  739              pm[px*2+1]     = pmt[c>>6];
  740              if(c>1)
  741                  c |= 0x1000;
  742              colors[px*2+1] = c;
  743          }
  744  
  745          offset = (source[2] & 0x7fff) * 0x10;
  746  
  747          xmod = 0x20;
  748          ymod = 0x20;
  749          for(py=0; py<sy; py++) {
  750              int xmod1 = xmod;
  751              int xpos1 = x;
  752              int ypos1 = y, ymod1 = ymod;
  753              for(px=0; px<sx; px++) {
  754                  int xmod2 = xmod1, xpos2 = xpos1;
  755                  int zy;
  756                  addoffset = 0x10*(flipx ? sx-px-1 : px) + 0x10*sx*(flipy ? sy-py-1 : py) + (flipy ? 7*2 : 0);
  757                  newoffset = offset + addoffset;
  758  
  759                  ymod1 = ymod;
  760                  ypos1 = y;
  761                  for(zy=0; zy<8; zy++) {
  762  
  763                      ymod1 += zoomy;
  764                      while(ymod1 >= 0x40) {
  765                          if(ypos1 >= min_y && ypos1 <= max_y) {
  766                              int zx;
  767                              xmod2 = xmod1;
  768                              xpos2 = xpos1;
  769  
  770                              for(zx=0; zx<8; zx++) {
  771                                  xmod2 += zoomx;
  772                                  while(xmod2 >= 0x40) {
  773                                      if(xpos2 >= min_x && xpos2 <= max_x) {
  774                                          int zx1 = flipx ? 7-zx : zx;
  775                                          UINT32 neweroffset = (newoffset+(zx1>>2))&0x1ffff; // crackdown sometimes attempts to use data past the end of spriteram
  776                                          int c = (sprite_ram[neweroffset] >> (((~zx1) & 3) << 2)) & 0xf;
  777                                          UINT8 *pri = &machine().priority_bitmap.pix8(ypos1, xpos2);
  778                                          if(!(*pri & pm[c])) {
  779                                              c = colors[c];
  780                                              if(c) {
  781                                                  UINT16 *dst = &bitmap.pix16(ypos1, xpos2);
  782                                                  if(c==1)
  783                                                      *dst = (*dst) | 0x2000;
  784                                                  else
  785                                                      *dst = c;
  786                                                  *pri = 0xff;
  787                                              }
  788                                          }
  789                                      }
  790                                      xmod2 -= 0x40;
  791                                      xpos2++;
  792                                  }
  793                              }
  794                          }
  795                          ymod1 -= 0x40;
  796                          ypos1++;
  797                      }
  798                      if(flipy)
  799                          newoffset -= 2;
  800                      else
  801                          newoffset += 2;
  802                  }
  803  
  804                  xpos1 = xpos2;
  805                  xmod1 = xmod2;
  806              }
  807              y    = ypos1;
  808              ymod = ymod1;
  809          }
  810      }
  811  }
  812  
  813  
  814  WRITE16_MEMBER(segas24_sprite::write)
  815  {
  816      COMBINE_DATA(sprite_ram + offset);
  817  }
  818  
  819  READ16_MEMBER(segas24_sprite::read)
  820  {
  821      return sprite_ram[offset];
  822  }
  823  
  824  
  825  segas24_mixer::segas24_mixer(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
  826      : device_t(mconfig, S24MIXER, "S24MIXER", tag, owner, clock)
  827  {
  828  }
  829  
  830  void segas24_mixer::device_start()
  831  {
  832      memset(mixer_reg, 0, sizeof(mixer_reg));
  833      save_item(NAME(mixer_reg));
  834  }
  835  
  836  WRITE16_MEMBER(segas24_mixer::write)
  837  {
  838      COMBINE_DATA(mixer_reg + offset);
  839  }
  840  
  841  READ16_MEMBER(segas24_mixer::read)
  842  {
  843      return mixer_reg[offset];
  844  }
  845  
  846  UINT16 segas24_mixer::get_reg(int reg)
  847  {
  848      return mixer_reg[reg];
  849  }
  850