wannabe optimizations
[fceu.git] / ppu.c
diff --git a/ppu.c b/ppu.c
index 0f2a47f..d2ea449 100644 (file)
--- a/ppu.c
+++ b/ppu.c
@@ -36,7 +36,7 @@
 uint8 SPRAM[0x100];
 static uint8 SPRBUF[0x100];
 
-static uint8 sprlinebuf[256+8];        
+static uint8 sprlinebuf[256+8];
 extern void BGRender(uint8 *target);
 extern int tosprite;
 
@@ -56,10 +56,10 @@ typedef struct {
 } SPR __attribute__((aligned(1)));
 
 typedef struct {
-  //   uint8 ca[2],atr,x; 
-       uint8 ca[2],atr,x; 
+  //   uint8 ca[2],atr,x;
+       uint8 ca[2],atr,x;
   //  union {  int z; }
-  
+
 
 } SPRB __attribute__((aligned(1)));
 
@@ -120,7 +120,7 @@ void FetchSpriteData(void)
                  if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
                   else C = VRAMADR(vadr);
 
-                 
+
                  dst.ca[0]=C[0];
                  dst.ca[1]=C[8];
                  dst.x=spr->x;
@@ -202,9 +202,8 @@ extern int FSkip;
 
 void RefreshSprite(uint8 *target)
 {
-       int n;
+       int n, minx=256;
         SPRB *spr;
-        uint8 *P=target;
 
         if(!nosprites) return;
        #ifdef FRAMESKIP
@@ -220,29 +219,30 @@ void RefreshSprite(uint8 *target)
        }
        #endif
 
-        FCEU_dwmemset(sprlinebuf,0x80808080,256);
         nosprites--;
         spr = (SPRB*)SPRBUF+nosprites;
 
        for(n=nosprites;n>=0;n--,spr--)
        {
-        register uint8 J,atr,c1,c2;
-       int x=spr->x;
-        uint8 *C;
-        uint8 *VB;
-                
-        P+=x;
-
-        c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
-       c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
+        register uint32 J;
 
         J=spr->ca[0]|spr->ca[1];
-       atr=spr->atr;
 
-                       if(J)
-                       {        
+        if (J)
+        {
+          register uint8 atr,c1,c2;
+          uint8 *C;
+          uint8 *VB;
+         int x=spr->x;
+         atr=spr->atr;
+
+          if (x < minx)
+         {
+           if (minx == 256) FCEU_dwmemset(sprlinebuf,0x80808080,256); // only clear sprite buff when we encounter first sprite
+           minx = x;
+         }
                         if(n==0 && SpriteBlurp && !(PPU_status&0x40))
-                        {  
+                        {
                         int z,ze=x+8;
                         if(ze>256) {ze=256;}
                         if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
@@ -277,113 +277,77 @@ void RefreshSprite(uint8 *target)
                         //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
                         }
 
+         c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
+        c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
+
         C = sprlinebuf+x;
          VB = (PALRAM+0x10)+((atr&3)<<2);
 
-         if(atr&SP_BACK) 
          {
+         J &= 0xff;
+         if(atr&SP_BACK) J |= 0x4000;
           if (atr&H_FLIP)
           {
-           if (J&0x02)  C[1]=VB[c1&3]|0x40;
-           if (J&0x01)  *C=VB[c2&3]|0x40;
+           if (J&0x02)  C[1]=VB[c1&3]|(J>>8);
+           if (J&0x01)  *C=VB[c2&3]|(J>>8);
            c1>>=2;c2>>=2;
-           if (J&0x08)  C[3]=VB[c1&3]|0x40;;
-           if (J&0x04)  C[2]=VB[c2&3]|0x40;;
+           if (J&0x08)  C[3]=VB[c1&3]|(J>>8);
+           if (J&0x04)  C[2]=VB[c2&3]|(J>>8);
            c1>>=2;c2>>=2;
-           if (J&0x20)  C[5]=VB[c1&3]|0x40;;
-           if (J&0x10)  C[4]=VB[c2&3]|0x40;;
+           if (J&0x20)  C[5]=VB[c1&3]|(J>>8);
+           if (J&0x10)  C[4]=VB[c2&3]|(J>>8);
            c1>>=2;c2>>=2;
-           if (J&0x80)  C[7]=VB[c1]|0x40;;
-           if (J&0x40)  C[6]=VB[c2]|0x40;;
+           if (J&0x80)  C[7]=VB[c1]|(J>>8);
+           if (J&0x40)  C[6]=VB[c2]|(J>>8);
          } else  {
-           if (J&0x02)  C[6]=VB[c1&3]|0x40;
-           if (J&0x01)  C[7]=VB[c2&3]|0x40;
+           if (J&0x02)  C[6]=VB[c1&3]|(J>>8);
+           if (J&0x01)  C[7]=VB[c2&3]|(J>>8);
           c1>>=2;c2>>=2;
-           if (J&0x08)  C[4]=VB[c1&3]|0x40;
-           if (J&0x04)  C[5]=VB[c2&3]|0x40;
+           if (J&0x08)  C[4]=VB[c1&3]|(J>>8);
+           if (J&0x04)  C[5]=VB[c2&3]|(J>>8);
            c1>>=2;c2>>=2;
-           if (J&0x20)  C[2]=VB[c1&3]|0x40;
-           if (J&0x10)  C[3]=VB[c2&3]|0x40;
+           if (J&0x20)  C[2]=VB[c1&3]|(J>>8);
+           if (J&0x10)  C[3]=VB[c2&3]|(J>>8);
            c1>>=2;c2>>=2;
-           if (J&0x80)  *C=VB[c1]|0x40;
-           if (J&0x40)  C[1]=VB[c2]|0x40;
+           if (J&0x80)  *C=VB[c1]|(J>>8);
+           if (J&0x40)  C[1]=VB[c2]|(J>>8);
          }
-         } else {
-          if (atr&H_FLIP)
-         {
-           if (J&0x02)  C[1]=VB[(c1&3)];
-           if (J&0x01)  *C=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x08)  C[3]=VB[(c1&3)];
-           if (J&0x04)  C[2]=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x20)  C[5]=VB[(c1&3)];
-           if (J&0x10)  C[4]=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x80)  C[7]=VB[c1];
-           if (J&0x40)  C[6]=VB[c2];
-          }else{                 
-           if (J&0x02)  C[6]=VB[(c1&3)];
-           if (J&0x01)  C[7]=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x08)  C[4]=VB[(c1&3)];
-           if (J&0x04)  C[5]=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x20)  C[2]=VB[(c1&3)];
-           if (J&0x10)  C[3]=VB[(c2&3)];
-           c1>>=2;c2>>=2;
-           if (J&0x80)  *C=VB[c1];
-           if (J&0x40)  C[1]=VB[c2];
-          }
          }
-        }
-       P-=x;
       }
+     }
 
      nosprites=0;
      #ifdef FRAMESKIP
      if(FSkip) return;
      #endif
+     if (minx == 256) return; // no visible sprites
 
      {
       uint8 n=((PPU[1]&4)^4)<<1;
+      if ((int)n < minx) n = minx & 0xfc;
       loopskie:
       {
        uint32 t=*(uint32 *)(sprlinebuf+n);
        if(t!=0x80808080)
        {
        #ifdef LSB_FIRST
-        if(!(t&0x80))
-        {
-         if(!(t&0x40))       // Normal sprite
-          P[n]=sprlinebuf[n];
-         else if(P[n]&64)        // behind bg sprite
-          P[n]=sprlinebuf[n];
+        uint32 tb=*(uint32 *)(target+n);
+        if(!(t&0x00000080) && (!(t&0x00000040) || (tb&0x00000040))) { // have sprite pixel AND (normal sprite OR behind bg with no bg)
+          tb &= ~0x000000ff; tb |= t & 0x000000ff;
         }
 
-        if(!(t&0x8000))
-        {
-         if(!(t&0x4000))       // Normal sprite
-          P[n+1]=(sprlinebuf+1)[n];
-         else if(P[n+1]&64)        // behind bg sprite
-          P[n+1]=(sprlinebuf+1)[n];
+        if(!(t&0x00008000) && (!(t&0x00004000) || (tb&0x00004000))) {
+          tb &= ~0x0000ff00; tb |= t & 0x0000ff00;
         }
 
-        if(!(t&0x800000))
-        {
-         if(!(t&0x400000))       // Normal sprite
-          P[n+2]=(sprlinebuf+2)[n];
-         else if(P[n+2]&64)        // behind bg sprite
-          P[n+2]=(sprlinebuf+2)[n];
+        if(!(t&0x00800000) && (!(t&0x00400000) || (tb&0x00400000))) {
+          tb &= ~0x00ff0000; tb |= t & 0x00ff0000;
         }
 
-        if(!(t&0x80000000))
-        {
-         if(!(t&0x40000000))       // Normal sprite
-          P[n+3]=(sprlinebuf+3)[n];
-         else if(P[n+3]&64)        // behind bg sprite
-          P[n+3]=(sprlinebuf+3)[n];
+        if(!(t&0x80000000) && (!(t&0x40000000) || (tb&0x40000000))) {
+          tb &= ~0xff000000; tb |= t & 0xff000000;
         }
+       *(uint32 *)(target+n)=tb;
        #else
         if(!(t&0x80000000))
         {
@@ -438,7 +402,7 @@ void FetchSpriteData(void)
        int vofs;
         uint8 P0=PPU[0];
 
-        
+
         spr=(SPR *)SPRAM;
         H=8;
 
@@ -482,11 +446,11 @@ void FetchSpriteData(void)
                         vadr+=t&8;
                   }
 
-                  // Fix this geniestage hack 
+                  // Fix this geniestage hack
                   if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
                   else C = VRAMADR(vadr);
 
-                  
+
                   dst.ca[0]=C[0];
                   dst.ca[1]=C[8];
                   dst.x=spr->x;
@@ -565,7 +529,7 @@ void FetchSpriteData(void)
         //if(ns>=7)
         //printf("%d %d\n",scanline,ns);
         if(ns>8) PPU_status|=0x20;     // Handle case when >8 sprites per
-//                                scanline option is enabled. 
+//                                scanline option is enabled.
        else if(PPU_hook)
        {
         for(n=0;n<(8-ns);n++)
@@ -582,7 +546,7 @@ void FetchSpriteData(void)
 
 void RefreshSprite(uint8 *target)
 {
-      
+
        int n,sprindex;
        SPRB *spr;
         uint8 *P=target;
@@ -603,7 +567,7 @@ void RefreshSprite(uint8 *target)
        int x=spr[sprindex].x;
         uint8 *C;
         uint8 *VB;
-                
+
         P+=x;
 
         c1=((spr[sprindex].ca[0]>>1)&0x55)|(spr[sprindex].ca[1]&0xAA);
@@ -613,9 +577,9 @@ void RefreshSprite(uint8 *target)
        atr=spr[sprindex].atr;
 
                        if(J)
-                       {        
+                       {
                         if(n==0 && SpriteBlurp && !(PPU_status&0x40))
-                        {  
+                        {
                         int z,ze=x+8;
                         if(ze>256) {ze=256;}
                         if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
@@ -655,7 +619,7 @@ void RefreshSprite(uint8 *target)
         C = &(sprlinebuf[(uint8)x]);
          VB = (PALRAM+0x10)+((atr&3)<<2);
 
-         if(atr&SP_BACK) 
+         if(atr&SP_BACK)
          {
           if (atr&H_FLIP)
           {
@@ -697,7 +661,7 @@ void RefreshSprite(uint8 *target)
            c1>>=2;c2>>=2;
            if (J&0x80)  C[7]=VB[c1];
            if (J&0x40)  C[6]=VB[c2];
-          }else{                 
+          }else{
            if (J&0x02)  C[6]=VB[(c1&3)];
            if (J&0x01)  C[7]=VB[(c2&3)];
            c1>>=2;c2>>=2;