gpfce patch part2
[fceu.git] / ppu.c
diff --git a/ppu.c b/ppu.c
new file mode 100644 (file)
index 0000000..0f2a47f
--- /dev/null
+++ b/ppu.c
@@ -0,0 +1,803 @@
+/**
+ *  For whatever reason, breaking this out of fce.c made sprites not corrupt
+ */
+
+
+#include        <string.h>
+#include       <stdio.h>
+#include       <stdlib.h>
+
+#include       "types.h"
+#include       "x6502.h"
+#include       "fce.h"
+#include       "sound.h"
+#include        "svga.h"
+#include       "netplay.h"
+#include       "general.h"
+#include       "endian.h"
+#include       "version.h"
+#include        "memory.h"
+
+#include       "cart.h"
+#include       "nsf.h"
+#include       "fds.h"
+#include       "ines.h"
+#include       "unif.h"
+#include        "cheat.h"
+
+#define MMC5SPRVRAMADR(V)      &MMC5SPRVPage[(V)>>10][(V)]
+//#define MMC5BGVRAMADR(V)      &MMC5BGVPage[(V)>>10][(V)]
+#define        VRAMADR(V)      &VPage[(V)>>10][(V)]
+
+#define        V_FLIP  0x80
+#define        H_FLIP  0x40
+#define        SP_BACK 0x20
+
+uint8 SPRAM[0x100];
+static uint8 SPRBUF[0x100];
+
+static uint8 sprlinebuf[256+8];        
+extern void BGRender(uint8 *target);
+extern int tosprite;
+
+
+static int maxsprites=8;
+
+
+void FCEUI_DisableSpriteLimitation(int a)
+{
+ maxsprites=a?64:8;
+}
+
+
+//int printed=1;
+typedef struct {
+        uint8 y,no,atr,x;
+} SPR __attribute__((aligned(1)));
+
+typedef struct {
+  //   uint8 ca[2],atr,x; 
+       uint8 ca[2],atr,x; 
+  //  union {  int z; }
+  
+
+} SPRB __attribute__((aligned(1)));
+
+
+
+static uint8 nosprites,SpriteBlurp;
+
+void FetchSpriteData(void)
+{
+       SPR *spr;
+       uint8 H;
+       int n,vofs;
+
+       spr=(SPR *)SPRAM;
+       H=8;
+
+       nosprites=SpriteBlurp=0;
+
+        vofs=(unsigned int)(PPU[0]&0x8&(((PPU[0]&0x20)^0x20)>>2))<<9;
+       H+=(PPU[0]&0x20)>>2;
+
+        if(!PPU_hook)
+         for(n=63;n>=0;n--,spr++)
+         {
+                if((unsigned int)(scanline-spr->y)>=H) continue;
+
+                if(nosprites<maxsprites)
+                {
+                 if(n==63) SpriteBlurp=1;
+
+                {
+                 SPRB dst;
+                 uint8 *C;
+                  int t;
+                  unsigned int vadr;
+
+                  t = (int)scanline-(spr->y);
+
+                  if (Sprite16)
+                   vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+                  else
+                   vadr = (spr->no<<4)+vofs;
+
+                  if (spr->atr&V_FLIP)
+                  {
+                        vadr+=7;
+                        vadr-=t;
+                        vadr+=(PPU[0]&0x20)>>1;
+                        vadr-=t&8;
+                  }
+                  else
+                  {
+                        vadr+=t;
+                        vadr+=t&8;
+                  }
+
+                 /* 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;
+                 dst.atr=spr->atr;
+
+
+                 *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
+                }
+
+                 nosprites++;
+                }
+                else
+                {
+                  PPU_status|=0x20;
+                  break;
+                }
+         }
+       else
+         for(n=63;n>=0;n--,spr++)
+         {
+                if((unsigned int)(scanline-spr->y)>=H) continue;
+
+                if(nosprites<maxsprites)
+                {
+                 if(n==63) SpriteBlurp=1;
+
+                 {
+                  SPRB dst;
+                  uint8 *C;
+                  int t;
+                  unsigned int vadr;
+
+                  t = (int)scanline-(spr->y);
+
+                  if (Sprite16)
+                   vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+                  else
+                   vadr = (spr->no<<4)+vofs;
+
+                  if (spr->atr&V_FLIP)
+                  {
+                        vadr+=7;
+                        vadr-=t;
+                        vadr+=(PPU[0]&0x20)>>1;
+                        vadr-=t&8;
+                  }
+                  else
+                  {
+                        vadr+=t;
+                        vadr+=t&8;
+                  }
+
+                  if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
+                  else C = VRAMADR(vadr);
+                  dst.ca[0]=C[0];
+                 PPU_hook(vadr);
+                  dst.ca[1]=C[8];
+                 PPU_hook(vadr|8);
+                  dst.x=spr->x;
+                  dst.atr=spr->atr;
+
+
+                  *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
+                 }
+
+                 nosprites++;
+                }
+                else
+                {
+                  PPU_status|=0x20;
+                  break;
+                }
+         }
+}
+
+#ifdef FRAMESKIP
+extern int FSkip;
+#endif
+
+void RefreshSprite(uint8 *target)
+{
+       int n;
+        SPRB *spr;
+        uint8 *P=target;
+
+        if(!nosprites) return;
+       #ifdef FRAMESKIP
+       if(FSkip)
+       {
+        if(!SpriteBlurp)
+        {
+         nosprites=0;
+         return;
+        }
+        else
+         nosprites=1;
+       }
+       #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);
+
+        J=spr->ca[0]|spr->ca[1];
+       atr=spr->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
+                        #ifdef FRAMESKIP
+                        || FSkip
+                        #endif
+                        ))
+                         BGRender(target);
+
+                        if(!(atr&H_FLIP))
+                        {
+                         for(z=x;z<ze;z++)
+                         {
+                          if(J&(0x80>>(z-x)))
+                          {
+                           if(!(target[z]&64))
+                            tosprite=z;
+                          }
+                         }
+                        }
+                        else
+                        {
+                          for(z=x;z<ze;z++)
+                          {
+                           if(J&(1<<(z-x)))
+                           {
+                            if(!(target[z]&64))
+                             tosprite=z;
+                           }
+                          }
+                        }
+                        //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
+                        }
+
+        C = sprlinebuf+x;
+         VB = (PALRAM+0x10)+((atr&3)<<2);
+
+         if(atr&SP_BACK) 
+         {
+          if (atr&H_FLIP)
+          {
+           if (J&0x02)  C[1]=VB[c1&3]|0x40;
+           if (J&0x01)  *C=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x08)  C[3]=VB[c1&3]|0x40;;
+           if (J&0x04)  C[2]=VB[c2&3]|0x40;;
+           c1>>=2;c2>>=2;
+           if (J&0x20)  C[5]=VB[c1&3]|0x40;;
+           if (J&0x10)  C[4]=VB[c2&3]|0x40;;
+           c1>>=2;c2>>=2;
+           if (J&0x80)  C[7]=VB[c1]|0x40;;
+           if (J&0x40)  C[6]=VB[c2]|0x40;;
+         } else  {
+           if (J&0x02)  C[6]=VB[c1&3]|0x40;
+           if (J&0x01)  C[7]=VB[c2&3]|0x40;
+          c1>>=2;c2>>=2;
+           if (J&0x08)  C[4]=VB[c1&3]|0x40;
+           if (J&0x04)  C[5]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x20)  C[2]=VB[c1&3]|0x40;
+           if (J&0x10)  C[3]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x80)  *C=VB[c1]|0x40;
+           if (J&0x40)  C[1]=VB[c2]|0x40;
+         }
+         } 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
+
+     {
+      uint8 n=((PPU[1]&4)^4)<<1;
+      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];
+        }
+
+        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&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&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];
+        }
+       #else
+        if(!(t&0x80000000))
+        {
+         if(!(t&0x40))       // Normal sprite
+          P[n]=sprlinebuf[n];
+         else if(P[n]&64)        // behind bg sprite
+          P[n]=sprlinebuf[n];
+        }
+
+        if(!(t&0x800000))
+        {
+         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&0x8000))
+        {
+         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&0x80))
+        {
+         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];
+        }
+       #endif
+       }
+      }
+      n+=4;
+      if(n) goto loopskie;
+     }
+}
+
+
+
+
+
+/*
+void FetchSpriteData(void)
+{
+        uint8 ns,sb;
+        SPR *spr;
+        uint8 H;
+       int n;
+       int vofs;
+        uint8 P0=PPU[0];
+
+        
+        spr=(SPR *)SPRAM;
+        H=8;
+
+        ns=sb=0;
+
+        vofs=(unsigned int)(P0&0x8&(((P0&0x20)^0x20)>>2))<<9;
+        H+=(P0&0x20)>>2;
+
+        if(!PPU_hook)
+         for(n=63;n>=0;n--,spr++)
+         {
+                if((unsigned int)(scanline-spr->y)>=H) continue;
+                //printf("%d, %u\n",scanline,(unsigned int)(scanline-spr->y));
+                if(ns<maxsprites)
+                {
+                 if(n==63) sb=1;
+
+                 {
+                  SPRB dst;
+                  uint8 *C;
+                  int t;
+                  unsigned int vadr;
+
+                  t = (int)scanline-(spr->y);
+
+                  if (Sprite16)
+                   vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+                  else
+                   vadr = (spr->no<<4)+vofs;
+
+                  if (spr->atr&V_FLIP)
+                  {
+                        vadr+=7;
+                        vadr-=t;
+                        vadr+=(P0&0x20)>>1;
+                        vadr-=t&8;
+                  }
+                  else
+                  {
+                        vadr+=t;
+                        vadr+=t&8;
+                  }
+
+                  // 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;
+                  dst.atr=spr->atr;
+
+                  *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
+                 }
+
+                 ns++;
+                }
+                else
+                {
+                  PPU_status|=0x20;
+                  break;
+                }
+         }
+        else
+         for(n=63;n>=0;n--,spr++)
+         {
+                if((unsigned int)(scanline-spr->y)>=H) continue;
+
+                if(ns<maxsprites)
+                {
+                 if(n==63) sb=1;
+
+                 {
+                  SPRB dst;
+                  uint8 *C;
+                  int t;
+                  unsigned int vadr;
+
+                  t = (int)scanline-(spr->y);
+
+                  if (Sprite16)
+                   vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+                  else
+                   vadr = (spr->no<<4)+vofs;
+
+                  if (spr->atr&V_FLIP)
+                  {
+                        vadr+=7;
+                        vadr-=t;
+                        vadr+=(P0&0x20)>>1;
+                        vadr-=t&8;
+                  }
+                  else
+                  {
+                        vadr+=t;
+                        vadr+=t&8;
+                  }
+
+                  if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
+                  else C = VRAMADR(vadr);
+                  dst.ca[0]=C[0];
+                 if(ns<8)
+                 {
+                  PPU_hook(0x2000);
+                   PPU_hook(vadr);
+                 }
+                  dst.ca[1]=C[8];
+                  dst.x=spr->x;
+                  dst.atr=spr->atr;
+
+
+                  *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
+                 }
+
+                 ns++;
+                }
+                else
+                {
+                  PPU_status|=0x20;
+                  break;
+                }
+         }
+        //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. 
+       else if(PPU_hook)
+       {
+        for(n=0;n<(8-ns);n++)
+        {
+                 PPU_hook(0x2000);
+                 PPU_hook(vofs);
+        }
+       }
+        numsprites=ns;
+        SpriteBlurp=sb;
+}
+
+
+
+void RefreshSprite(uint8 *target)
+{
+      
+       int n,sprindex;
+       SPRB *spr;
+        uint8 *P=target;
+
+        //if (printed) {  printf("SPRB: %d  SPR: %d\n", sizeof(SPRB), sizeof(SPR)); printed=0; }
+        if(!numsprites) return;
+
+        FCEU_dwmemset(sprlinebuf,0x80808080,256);
+
+        numsprites--;
+        sprindex=numsprites;
+        spr = (SPRB*)SPRBUF;
+
+       //       for(n=nosprites;n>=0;n--,spr--)
+       for(n=numsprites;n>=0;n--,sprindex--)
+       {
+        uint8 J,atr,c1,c2;
+       int x=spr[sprindex].x;
+        uint8 *C;
+        uint8 *VB;
+                
+        P+=x;
+
+        c1=((spr[sprindex].ca[0]>>1)&0x55)|(spr[sprindex].ca[1]&0xAA);
+       c2=(spr[sprindex].ca[0]&0x55)|((spr[sprindex].ca[1]<<1)&0xAA);
+
+        J=spr[sprindex].ca[0]|spr[sprindex].ca[1];
+       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
+                        #ifdef FRAMESKIP
+                        || FSkip
+                        #endif
+                        ))
+                          // nothing wrong with this
+                        BGRender(target);
+
+                        if(!(atr&H_FLIP))
+                        {
+                         for(z=x;z<ze;z++)
+                         {
+                          if(J&(0x80>>(z-x)))
+                          {
+                           if(!(target[z]&64))
+                            tosprite=z;
+                          }
+                         }
+                        }
+                        else
+                        {
+                          for(z=x;z<ze;z++)
+                          {
+                           if(J&(1<<(z-x)))
+                           {
+                            if(!(target[z]&64))
+                             tosprite=z;
+                           }
+                          }
+                        }
+                        //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
+                        }
+
+        //C = sprlinebuf+(uint8)x;
+        C = &(sprlinebuf[(uint8)x]);
+         VB = (PALRAM+0x10)+((atr&3)<<2);
+
+         if(atr&SP_BACK) 
+         {
+          if (atr&H_FLIP)
+          {
+           if (J&0x02)  C[1]=VB[c1&3]|0x40;
+           if (J&0x01)  *C=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x08)  C[3]=VB[c1&3]|0x40;
+           if (J&0x04)  C[2]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x20)  C[5]=VB[c1&3]|0x40;
+           if (J&0x10)  C[4]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x80)  C[7]=VB[c1]|0x40;
+           if (J&0x40)  C[6]=VB[c2]|0x40;
+         } else  {
+           if (J&0x02)  C[6]=VB[c1&3]|0x40;
+           if (J&0x01)  C[7]=VB[c2&3]|0x40;
+          c1>>=2;c2>>=2;
+           if (J&0x08)  C[4]=VB[c1&3]|0x40;
+           if (J&0x04)  C[5]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x20)  C[2]=VB[c1&3]|0x40;
+           if (J&0x10)  C[3]=VB[c2&3]|0x40;
+           c1>>=2;c2>>=2;
+           if (J&0x80)  *C=VB[c1]|0x40;
+           if (J&0x40)  C[1]=VB[c2]|0x40;
+         }
+         } 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;
+      }
+
+     numsprites=0;
+     #ifdef FRAMESKIP
+     if(FSkip) return;
+     #endif
+
+     {
+      uint8 n=((PPU[1]&4)^4)<<1;
+      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];
+        }
+
+        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&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&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];
+        }
+       #else
+        if(!(t&0x80000000))
+        {
+         if(!(t&0x40))       // Normal sprite
+          P[n]=sprlinebuf[n];
+         else if(P[n]&64)        // behind bg sprite
+          P[n]=sprlinebuf[n];
+        }
+
+        if(!(t&0x800000))
+        {
+         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&0x8000))
+        {
+         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&0x80))
+        {
+         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];
+        }
+       #endif
+       }
+      }
+      n+=4;
+      if(n) goto loopskie;
+     }
+}
+
+
+*/