Previous 15994 Revisions Next

r7540 Tuesday 9th March, 2010 at 14:28:14 UTC by Fabio Priuli
[SNES] Changed OAM code to create sprite list for each line based on OBSEL settings of the previous line
[src/mame/includes]snes.h
[src/mame/machine]snes.c
[src/mame/video]snes.c

src/mame/machine/snes.c
r7539r7540
777777         snes_ppu.screen_brightness = (data & 0x0f) + 1;
778778         break;
779779      case OBSEL:      /* Object size and data area designation */
780         snes_ppu.layer[SNES_OAM].charmap = (data & 0x03) << 1;
781         snes_ppu.oam.name_select = (((data & 0x18) >> 3) * 0x1000) << 1;
782         /* Determine object size */
783         switch ((data & 0xe0) >> 5)
784         {
785            case 0:         /* 8 & 16 */
786               snes_ppu.oam.size[0] = 1;
787               snes_ppu.oam.size[1] = 2;
788               break;
789            case 1:         /* 8 & 32 */
790               snes_ppu.oam.size[0] = 1;
791               snes_ppu.oam.size[1] = 4;
792               break;
793            case 2:         /* 8 & 64 */
794               snes_ppu.oam.size[0] = 1;
795               snes_ppu.oam.size[1] = 8;
796               break;
797            case 3:         /* 16 & 32 */
798               snes_ppu.oam.size[0] = 2;
799               snes_ppu.oam.size[1] = 4;
800               break;
801            case 4:         /* 16 & 64 */
802               snes_ppu.oam.size[0] = 2;
803               snes_ppu.oam.size[1] = 8;
804               break;
805            case 5:         /* 32 & 64 */
806               snes_ppu.oam.size[0] = 4;
807               snes_ppu.oam.size[1] = 8;
808               break;
809            default:
810               /* Unknown size so default to 8 & 16 */
811               logerror("Object size unsupported: %d\n", (data & 0xe0) >> 5);
812
813               snes_ppu.oam.size[0] = 1;
814               snes_ppu.oam.size[1] = 2;
815#ifdef SNES_DBG_REG_W
816               mame_printf_debug("Object size unsupported: %d\n", (data & 0xe0) >> 5);
817#endif
818         }
780         snes_ppu.oam.next_charmap = (data & 0x03) << 1;
781         snes_ppu.oam.next_name_select = (((data & 0x18) >> 3) * 0x1000) << 1;
782         snes_ppu.oam.next_size = (data & 0xe0) >> 5;
819783         break;
820784      case OAMADDL:   /* Address for accessing OAM (low) */
821785         snes_ppu.oam.address_low = data;
r7539r7540
827791         snes_ppu.oam.address_high = data & 0x1;
828792         snes_ppu.oam.saved_address_high = data;
829793         snes_ppu.oam.address = ((data & 0x1) << 8) + snes_ppu.oam.address_low;
830         snes_ppu.oam.priority_rotation = (data & 0x80) ? 1 : 0;
794         snes_ppu.oam.priority_rotation = BIT(data, 7);
831795         snes_ram[OAMDATA] = 0;
832796         break;
833797      case OAMDATA:   /* Data for OAM write (DW) */
src/mame/includes/snes.h
r7539r7540
525525      UINT8 saved_address_high;
526526      UINT16 address;
527527      UINT16 priority_rotation;
528      UINT8 size[2];
528      UINT8 next_charmap;
529      UINT8 next_size;
530      UINT8 size;
531      UINT32 next_name_select;
529532      UINT32 name_select;
530533      UINT8 first_sprite;
531534      UINT8 flip;
r7539r7540
584587   UINT8 clipmasks[6][SNES_SCR_WIDTH];
585588   UINT8 update_windows;
586589   UINT8 update_offsets;
590   UINT8 update_oam_list;
587591   UINT8 mode;
588592   UINT8 interlace; //doubles the visible resolution
589593   UINT8 obj_interlace;
src/mame/video/snes.c
r7539r7540
989989 * FIXME: We need to support high priority bit
990990 *********************************************/
991991
992struct OAM
993{
994   UINT16 tile;
995   INT16 x, y;
996   UINT8 size, vflip, hflip, priority_bits, pal;
997   int height, width;
998};
999
1000static struct OAM oam_list[SNES_SCR_WIDTH / 2];
1001
1002static void snes_update_obsel( void )
1003{
1004   snes_ppu.layer[SNES_OAM].charmap = snes_ppu.oam.next_charmap;
1005   snes_ppu.oam.name_select = snes_ppu.oam.next_name_select;
1006
1007   if (snes_ppu.oam.size != snes_ppu.oam.next_size)
1008   {
1009      snes_ppu.oam.size = snes_ppu.oam.next_size;
1010      snes_ppu.update_oam_list = 1;
1011   }
1012}
1013
1014static void snes_oam_list_build( void )
1015{
1016   UINT8 *oamram = (UINT8 *)snes_oam;
1017   INT16 oam = 0x1ff;
1018   UINT16 oam_extra = oam + 0x20;
1019   UINT16 extra = 0;
1020   int i;
1021
1022   snes_ppu.update_oam_list = 0;      // eventually, we can optimize the code by only calling this function when there is a change in size
1023
1024   for (i = 128; i > 0; i--)
1025   {
1026      if ((i % 4) == 0)
1027         extra = oamram[oam_extra--];
1028
1029      oam_list[i].vflip = (oamram[oam] & 0x80) >> 7;
1030      oam_list[i].hflip = (oamram[oam] & 0x40) >> 6;
1031      oam_list[i].priority_bits = (oamram[oam] & 0x30) >> 4;
1032      oam_list[i].pal = 128 + ((oamram[oam] & 0x0e) << 3);
1033      oam_list[i].tile = (oamram[oam--] & 0x1) << 8;
1034      oam_list[i].tile |= oamram[oam--];
1035      oam_list[i].y = oamram[oam--] + 1;   /* We seem to need to add one here.... */
1036      oam_list[i].x = oamram[oam--];
1037      oam_list[i].size = (extra & 0x80) >> 7;
1038      extra <<= 1;
1039      oam_list[i].x |= ((extra & 0x80) << 1);
1040      extra <<= 1;
1041      oam_list[i].y *= snes_ppu.obj_interlace;
1042
1043      /* Adjust if past maximum position */
1044      if (oam_list[i].y >= snes_ppu.beam.last_visible_line * snes_ppu.interlace)
1045         oam_list[i].y -= 256 * snes_ppu.interlace;
1046      if (oam_list[i].x > 255)
1047         oam_list[i].x -= 512;
1048
1049      /* Determine object size */
1050      switch (snes_ppu.oam.size)
1051      {
1052      case 0:         /* 8x8 or 16x16 */
1053         oam_list[i].width  = oam_list[i].size ? 2 : 1;
1054         oam_list[i].height = oam_list[i].size ? 2 : 1;
1055         break;
1056      case 1:         /* 8x8 or 32x32 */
1057         oam_list[i].width  = oam_list[i].size ? 4 : 1;
1058         oam_list[i].height = oam_list[i].size ? 4 : 1;
1059         break;
1060      case 2:         /* 8x8 or 64x64 */
1061         oam_list[i].width  = oam_list[i].size ? 8 : 1;
1062         oam_list[i].height = oam_list[i].size ? 8 : 1;
1063         break;
1064      case 3:         /* 16x16 or 32x32 */
1065         oam_list[i].width  = oam_list[i].size ? 4 : 2;
1066         oam_list[i].height = oam_list[i].size ? 4 : 2;
1067         break;
1068      case 4:         /* 16x16 or 64x64 */
1069         oam_list[i].width  = oam_list[i].size ? 8 : 2;
1070         oam_list[i].height = oam_list[i].size ? 8 : 2;
1071         break;
1072      case 5:         /* 32x32 or 64x64 */
1073         oam_list[i].width  = oam_list[i].size ? 8 : 4;
1074         oam_list[i].height = oam_list[i].size ? 8 : 4;
1075         break;
1076      case 6:         /* undocumented: 16x32 or 32x64 */
1077         oam_list[i].width  = oam_list[i].size ? 4 : 2;
1078         oam_list[i].height = oam_list[i].size ? 8 : 4;
1079         if (snes_ppu.obj_interlace && !oam_list[i].size)
1080            oam_list[i].height = 2;
1081         break;
1082      case 7:         /* undocumented: 16x32 or 32x32 */
1083         oam_list[i].width  = oam_list[i].size ? 4 : 2;
1084         oam_list[i].height = oam_list[i].size ? 4 : 4;
1085         if (snes_ppu.obj_interlace && !oam_list[i].size)
1086            oam_list[i].height = 2;
1087         break;
1088      default:
1089         /* we should never enter here... */
1090         logerror("Object size unsupported: %d\n", snes_ppu.oam.size);
1091         break;
1092      }
1093   }
1094}
1095
9921096static void snes_update_objects( UINT8 priority_tbl, UINT16 curline )
9931097{
9941098   INT8 xs, ys;
9951099   UINT8 line;
996   UINT16 oam_extra, extra;
997   INT16 oam;
9981100   UINT8 range_over = 0, time_over = 0;
999   UINT8 size, vflip, hflip, priority, pal, blend;
1101   UINT8 height, width, vflip, hflip, priority, pal, blend;
10001102   UINT16 tile;
10011103   INT16 i, x, y;
1002   UINT8 *oamram = (UINT8 *)snes_oam;
10031104   UINT32 name_sel = 0, charaddr;
10041105   static const UINT8 table_obj_priority[10][4] = {
10051106                  {2, 5, 8, 11},   // mode 0
r7539r7540
10321133
10331134   charaddr = snes_ppu.layer[SNES_OAM].charmap << 13;
10341135
1035   oam = 0x1ff;
1036   oam_extra = oam + 0x20;
1037   extra = 0;
10381136   for (i = 128; i > 0; i--)
10391137   {
1040      if ((i % 4) == 0)
1041         extra = oamram[oam_extra--];
1138      tile = oam_list[i].tile;
1139      x = oam_list[i].x;
1140      y = oam_list[i].y;
1141      height = oam_list[i].height;
1142      width = oam_list[i].width;
1143      vflip = oam_list[i].vflip;
1144      hflip = oam_list[i].hflip;
1145      priority = table_obj_priority[priority_tbl][oam_list[i].priority_bits];
1146      pal = oam_list[i].pal;
10421147
1043      vflip = (oamram[oam] & 0x80) >> 7;
1044      hflip = (oamram[oam] & 0x40) >> 6;
1045      priority = table_obj_priority[priority_tbl][(oamram[oam] & 0x30) >> 4];
1046      pal = 128 + ((oamram[oam] & 0x0e) << 3);
1047      tile = (oamram[oam--] & 0x1) << 8;
1048      tile |= oamram[oam--];
1049      y = oamram[oam--] + 1;   /* We seem to need to add one here.... */
1050      x = oamram[oam--];
1051      size = (extra & 0x80) >> 7;
1052      extra <<= 1;
1053      x |= ((extra & 0x80) << 1);
1054      extra <<= 1;
1055      y *= snes_ppu.obj_interlace;
1056
1057      /* Adjust if past maximum position */
1058      if (y >= snes_ppu.beam.last_visible_line*snes_ppu.interlace)
1059         y -= 256*snes_ppu.interlace;
1060      if (x > 255)
1061         x -= 512;
1062
10631148      /* Draw sprite if it intersects the current line */
1064      if (curline >= y && curline < (y + (snes_ppu.oam.size[size] << 3)))
1149      if (curline >= y && curline < (y + (height << 3)))
10651150      {
10661151         /* Only objects using palettes 4-7 can be transparent */
10671152         blend = (pal < 192) ? 1 : 0;
r7539r7540
10731158         line = (curline - y) % 8;
10741159         if (vflip)
10751160         {
1076            ys = snes_ppu.oam.size[size] - ys - 1;
1161            ys = height - ys - 1;
10771162            line = (-1 * line) + 7;
10781163         }
10791164         line <<= 1;
r7539r7540
10811166         if (hflip)
10821167         {
10831168            UINT8 count = 0;
1084            for (xs = (snes_ppu.oam.size[size] - 1); xs >= 0; xs--)
1169            for (xs = (width - 1); xs >= 0; xs--)
10851170            {
10861171               if ((x + (count << 3) < SNES_SCR_WIDTH))
10871172               {
r7539r7540
10921177         }
10931178         else
10941179         {
1095            for (xs = 0; xs < snes_ppu.oam.size[size]; xs++)
1180            for (xs = 0; xs < width; xs++)
10961181            {
10971182               if ((x + (xs << 3) < SNES_SCR_WIDTH))
10981183               {
r7539r7540
12521337
12531338static void snes_draw_screens( UINT16 curline )
12541339{
1340   snes_oam_list_build();
1341
12551342   switch (snes_ppu.mode)
12561343   {
12571344      case 0: snes_update_mode_0(curline); break;      /* Mode 0 */
r7539r7540
12641351      case 7: snes_update_mode_7(curline); break;      /* Mode 7 - Supports direct colour */
12651352   }
12661353}
1267
1354   
12681355/*********************************************
12691356 * snes_update_windowmasks()
12701357 *
r7539r7540
14941581{
14951582   int y;
14961583
1584   snes_update_obsel();
1585
14971586   /*NTSC SNES draw range is 1-225. */
14981587   for (y = cliprect->min_y; y <= cliprect->max_y; y++)
1588   {
14991589      snes_refresh_scanline(screen->machine, bitmap, y + 1);
1590      snes_update_obsel();
1591   }
15001592   return 0;
15011593}
15021594
r7539r7540
16171709            snes_ram[BG4SC] & 0x3,
16181710            (snes_ram[BG4SC] & 0xfc) << 9,
16191711            snes_ppu.layer[SNES_BG4].charmap << 13 );
1620      logerror("%sO %s%s%s%s%s%c%s%s%d%d       %4X",
1712      logerror("%sO %s%s%s%s%s%c%s%s       %4X",
16211713            debug_options.bg_disabled[4]?" ":"*",
16221714            (snes_ram[TM] & 0x10)?"M":" ",
16231715            (snes_ram[TS] & 0x10)?"S":" ",
r7539r7540
16271719            WINLOGIC[(snes_ram[WOBJLOG] & 0x3)],
16281720            (snes_ram[WOBJSEL] & 0x2)?((snes_ram[WOBJSEL] & 0x1)?"o":"i"):" ",
16291721            (snes_ram[WOBJSEL] & 0x8)?((snes_ram[WOBJSEL] & 0x4)?"o":"i"):" ",
1630            snes_ppu.oam.size[0], snes_ppu.oam.size[1],
16311722            snes_ppu.layer[SNES_OAM].charmap << 13 );
16321723      logerror("%sB   %s  %c%s%s",
16331724            debug_options.bg_disabled[5]?" ":"*",

Previous 15994 Revisions Next


© 1998-2018 The MESS Team