0f2a47fea9a6bb41aa7755a787a8c7fc7b99ba4b
[fceu.git] / ppu.c
1 /**
2  *  For whatever reason, breaking this out of fce.c made sprites not corrupt
3  */
4
5
6 #include        <string.h>
7 #include        <stdio.h>
8 #include        <stdlib.h>
9
10 #include        "types.h"
11 #include        "x6502.h"
12 #include        "fce.h"
13 #include        "sound.h"
14 #include        "svga.h"
15 #include        "netplay.h"
16 #include        "general.h"
17 #include        "endian.h"
18 #include        "version.h"
19 #include        "memory.h"
20
21 #include        "cart.h"
22 #include        "nsf.h"
23 #include        "fds.h"
24 #include        "ines.h"
25 #include        "unif.h"
26 #include        "cheat.h"
27
28 #define MMC5SPRVRAMADR(V)      &MMC5SPRVPage[(V)>>10][(V)]
29 //#define MMC5BGVRAMADR(V)      &MMC5BGVPage[(V)>>10][(V)]
30 #define VRAMADR(V)      &VPage[(V)>>10][(V)]
31
32 #define V_FLIP  0x80
33 #define H_FLIP  0x40
34 #define SP_BACK 0x20
35
36 uint8 SPRAM[0x100];
37 static uint8 SPRBUF[0x100];
38
39 static uint8 sprlinebuf[256+8];        
40 extern void BGRender(uint8 *target);
41 extern int tosprite;
42
43
44 static int maxsprites=8;
45
46
47 void FCEUI_DisableSpriteLimitation(int a)
48 {
49  maxsprites=a?64:8;
50 }
51
52
53 //int printed=1;
54 typedef struct {
55         uint8 y,no,atr,x;
56 } SPR __attribute__((aligned(1)));
57
58 typedef struct {
59   //    uint8 ca[2],atr,x; 
60         uint8 ca[2],atr,x; 
61   //  union {  int z; }
62   
63
64 } SPRB __attribute__((aligned(1)));
65
66
67
68 static uint8 nosprites,SpriteBlurp;
69
70 void FetchSpriteData(void)
71 {
72         SPR *spr;
73         uint8 H;
74         int n,vofs;
75
76         spr=(SPR *)SPRAM;
77         H=8;
78
79         nosprites=SpriteBlurp=0;
80
81         vofs=(unsigned int)(PPU[0]&0x8&(((PPU[0]&0x20)^0x20)>>2))<<9;
82         H+=(PPU[0]&0x20)>>2;
83
84         if(!PPU_hook)
85          for(n=63;n>=0;n--,spr++)
86          {
87                 if((unsigned int)(scanline-spr->y)>=H) continue;
88
89                 if(nosprites<maxsprites)
90                 {
91                  if(n==63) SpriteBlurp=1;
92
93                  {
94                   SPRB dst;
95                   uint8 *C;
96                   int t;
97                   unsigned int vadr;
98
99                   t = (int)scanline-(spr->y);
100
101                   if (Sprite16)
102                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
103                   else
104                    vadr = (spr->no<<4)+vofs;
105
106                   if (spr->atr&V_FLIP)
107                   {
108                         vadr+=7;
109                         vadr-=t;
110                         vadr+=(PPU[0]&0x20)>>1;
111                         vadr-=t&8;
112                   }
113                   else
114                   {
115                         vadr+=t;
116                         vadr+=t&8;
117                   }
118
119                   /* Fix this geniestage hack */
120                   if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
121                   else C = VRAMADR(vadr);
122
123                   
124                   dst.ca[0]=C[0];
125                   dst.ca[1]=C[8];
126                   dst.x=spr->x;
127                   dst.atr=spr->atr;
128
129
130                   *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
131                  }
132
133                  nosprites++;
134                 }
135                 else
136                 {
137                   PPU_status|=0x20;
138                   break;
139                 }
140          }
141         else
142          for(n=63;n>=0;n--,spr++)
143          {
144                 if((unsigned int)(scanline-spr->y)>=H) continue;
145
146                 if(nosprites<maxsprites)
147                 {
148                  if(n==63) SpriteBlurp=1;
149
150                  {
151                   SPRB dst;
152                   uint8 *C;
153                   int t;
154                   unsigned int vadr;
155
156                   t = (int)scanline-(spr->y);
157
158                   if (Sprite16)
159                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
160                   else
161                    vadr = (spr->no<<4)+vofs;
162
163                   if (spr->atr&V_FLIP)
164                   {
165                         vadr+=7;
166                         vadr-=t;
167                         vadr+=(PPU[0]&0x20)>>1;
168                         vadr-=t&8;
169                   }
170                   else
171                   {
172                         vadr+=t;
173                         vadr+=t&8;
174                   }
175
176                   if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
177                   else C = VRAMADR(vadr);
178                   dst.ca[0]=C[0];
179                   PPU_hook(vadr);
180                   dst.ca[1]=C[8];
181                   PPU_hook(vadr|8);
182                   dst.x=spr->x;
183                   dst.atr=spr->atr;
184
185
186                   *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
187                  }
188
189                  nosprites++;
190                 }
191                 else
192                 {
193                   PPU_status|=0x20;
194                   break;
195                 }
196          }
197 }
198
199 #ifdef FRAMESKIP
200 extern int FSkip;
201 #endif
202
203 void RefreshSprite(uint8 *target)
204 {
205         int n;
206         SPRB *spr;
207         uint8 *P=target;
208
209         if(!nosprites) return;
210         #ifdef FRAMESKIP
211         if(FSkip)
212         {
213          if(!SpriteBlurp)
214          {
215           nosprites=0;
216           return;
217          }
218          else
219           nosprites=1;
220         }
221         #endif
222
223         FCEU_dwmemset(sprlinebuf,0x80808080,256);
224         nosprites--;
225         spr = (SPRB*)SPRBUF+nosprites;
226
227        for(n=nosprites;n>=0;n--,spr--)
228        {
229         register uint8 J,atr,c1,c2;
230         int x=spr->x;
231         uint8 *C;
232         uint8 *VB;
233                 
234         P+=x;
235
236         c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
237         c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
238
239         J=spr->ca[0]|spr->ca[1];
240         atr=spr->atr;
241
242                        if(J)
243                        {        
244                         if(n==0 && SpriteBlurp && !(PPU_status&0x40))
245                         {  
246                          int z,ze=x+8;
247                          if(ze>256) {ze=256;}
248                          if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
249                          #ifdef FRAMESKIP
250                          || FSkip
251                          #endif
252                          ))
253                           BGRender(target);
254
255                          if(!(atr&H_FLIP))
256                          {
257                           for(z=x;z<ze;z++)
258                           {
259                            if(J&(0x80>>(z-x)))
260                            {
261                             if(!(target[z]&64))
262                              tosprite=z;
263                            }
264                           }
265                          }
266                          else
267                          {
268                           for(z=x;z<ze;z++)
269                           {
270                            if(J&(1<<(z-x)))
271                            {
272                             if(!(target[z]&64))
273                              tosprite=z;
274                            }
275                           }
276                          }
277                          //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
278                         }
279
280          C = sprlinebuf+x;
281          VB = (PALRAM+0x10)+((atr&3)<<2);
282
283          if(atr&SP_BACK) 
284          {
285           if (atr&H_FLIP)
286           {
287            if (J&0x02)  C[1]=VB[c1&3]|0x40;
288            if (J&0x01)  *C=VB[c2&3]|0x40;
289            c1>>=2;c2>>=2;
290            if (J&0x08)  C[3]=VB[c1&3]|0x40;;
291            if (J&0x04)  C[2]=VB[c2&3]|0x40;;
292            c1>>=2;c2>>=2;
293            if (J&0x20)  C[5]=VB[c1&3]|0x40;;
294            if (J&0x10)  C[4]=VB[c2&3]|0x40;;
295            c1>>=2;c2>>=2;
296            if (J&0x80)  C[7]=VB[c1]|0x40;;
297            if (J&0x40)  C[6]=VB[c2]|0x40;;
298           } else  {
299            if (J&0x02)  C[6]=VB[c1&3]|0x40;
300            if (J&0x01)  C[7]=VB[c2&3]|0x40;
301            c1>>=2;c2>>=2;
302            if (J&0x08)  C[4]=VB[c1&3]|0x40;
303            if (J&0x04)  C[5]=VB[c2&3]|0x40;
304            c1>>=2;c2>>=2;
305            if (J&0x20)  C[2]=VB[c1&3]|0x40;
306            if (J&0x10)  C[3]=VB[c2&3]|0x40;
307            c1>>=2;c2>>=2;
308            if (J&0x80)  *C=VB[c1]|0x40;
309            if (J&0x40)  C[1]=VB[c2]|0x40;
310           }
311          } else {
312           if (atr&H_FLIP)
313           {
314            if (J&0x02)  C[1]=VB[(c1&3)];
315            if (J&0x01)  *C=VB[(c2&3)];
316            c1>>=2;c2>>=2;
317            if (J&0x08)  C[3]=VB[(c1&3)];
318            if (J&0x04)  C[2]=VB[(c2&3)];
319            c1>>=2;c2>>=2;
320            if (J&0x20)  C[5]=VB[(c1&3)];
321            if (J&0x10)  C[4]=VB[(c2&3)];
322            c1>>=2;c2>>=2;
323            if (J&0x80)  C[7]=VB[c1];
324            if (J&0x40)  C[6]=VB[c2];
325           }else{                 
326            if (J&0x02)  C[6]=VB[(c1&3)];
327            if (J&0x01)  C[7]=VB[(c2&3)];
328            c1>>=2;c2>>=2;
329            if (J&0x08)  C[4]=VB[(c1&3)];
330            if (J&0x04)  C[5]=VB[(c2&3)];
331            c1>>=2;c2>>=2;
332            if (J&0x20)  C[2]=VB[(c1&3)];
333            if (J&0x10)  C[3]=VB[(c2&3)];
334            c1>>=2;c2>>=2;
335            if (J&0x80)  *C=VB[c1];
336            if (J&0x40)  C[1]=VB[c2];
337           }
338          }
339         }
340        P-=x;
341       }
342
343      nosprites=0;
344      #ifdef FRAMESKIP
345      if(FSkip) return;
346      #endif
347
348      {
349       uint8 n=((PPU[1]&4)^4)<<1;
350       loopskie:
351       {
352        uint32 t=*(uint32 *)(sprlinebuf+n);
353        if(t!=0x80808080)
354        {
355         #ifdef LSB_FIRST
356         if(!(t&0x80))
357         {
358          if(!(t&0x40))       // Normal sprite
359           P[n]=sprlinebuf[n];
360          else if(P[n]&64)        // behind bg sprite
361           P[n]=sprlinebuf[n];
362         }
363
364         if(!(t&0x8000))
365         {
366          if(!(t&0x4000))       // Normal sprite
367           P[n+1]=(sprlinebuf+1)[n];
368          else if(P[n+1]&64)        // behind bg sprite
369           P[n+1]=(sprlinebuf+1)[n];
370         }
371
372         if(!(t&0x800000))
373         {
374          if(!(t&0x400000))       // Normal sprite
375           P[n+2]=(sprlinebuf+2)[n];
376          else if(P[n+2]&64)        // behind bg sprite
377           P[n+2]=(sprlinebuf+2)[n];
378         }
379
380         if(!(t&0x80000000))
381         {
382          if(!(t&0x40000000))       // Normal sprite
383           P[n+3]=(sprlinebuf+3)[n];
384          else if(P[n+3]&64)        // behind bg sprite
385           P[n+3]=(sprlinebuf+3)[n];
386         }
387         #else
388         if(!(t&0x80000000))
389         {
390          if(!(t&0x40))       // Normal sprite
391           P[n]=sprlinebuf[n];
392          else if(P[n]&64)        // behind bg sprite
393           P[n]=sprlinebuf[n];
394         }
395
396         if(!(t&0x800000))
397         {
398          if(!(t&0x4000))       // Normal sprite
399           P[n+1]=(sprlinebuf+1)[n];
400          else if(P[n+1]&64)        // behind bg sprite
401           P[n+1]=(sprlinebuf+1)[n];
402         }
403
404         if(!(t&0x8000))
405         {
406          if(!(t&0x400000))       // Normal sprite
407           P[n+2]=(sprlinebuf+2)[n];
408          else if(P[n+2]&64)        // behind bg sprite
409           P[n+2]=(sprlinebuf+2)[n];
410         }
411
412         if(!(t&0x80))
413         {
414          if(!(t&0x40000000))       // Normal sprite
415           P[n+3]=(sprlinebuf+3)[n];
416          else if(P[n+3]&64)        // behind bg sprite
417           P[n+3]=(sprlinebuf+3)[n];
418         }
419         #endif
420        }
421       }
422       n+=4;
423       if(n) goto loopskie;
424      }
425 }
426
427
428
429
430
431 /*
432 void FetchSpriteData(void)
433 {
434         uint8 ns,sb;
435         SPR *spr;
436         uint8 H;
437         int n;
438         int vofs;
439         uint8 P0=PPU[0];
440
441         
442         spr=(SPR *)SPRAM;
443         H=8;
444
445         ns=sb=0;
446
447         vofs=(unsigned int)(P0&0x8&(((P0&0x20)^0x20)>>2))<<9;
448         H+=(P0&0x20)>>2;
449
450         if(!PPU_hook)
451          for(n=63;n>=0;n--,spr++)
452          {
453                 if((unsigned int)(scanline-spr->y)>=H) continue;
454                 //printf("%d, %u\n",scanline,(unsigned int)(scanline-spr->y));
455                 if(ns<maxsprites)
456                 {
457                  if(n==63) sb=1;
458
459                  {
460                   SPRB dst;
461                   uint8 *C;
462                   int t;
463                   unsigned int vadr;
464
465                   t = (int)scanline-(spr->y);
466
467                   if (Sprite16)
468                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
469                   else
470                    vadr = (spr->no<<4)+vofs;
471
472                   if (spr->atr&V_FLIP)
473                   {
474                         vadr+=7;
475                         vadr-=t;
476                         vadr+=(P0&0x20)>>1;
477                         vadr-=t&8;
478                   }
479                   else
480                   {
481                         vadr+=t;
482                         vadr+=t&8;
483                   }
484
485                   // Fix this geniestage hack 
486                   if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
487                   else C = VRAMADR(vadr);
488
489                   
490                   dst.ca[0]=C[0];
491                   dst.ca[1]=C[8];
492                   dst.x=spr->x;
493                   dst.atr=spr->atr;
494
495                   *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
496                  }
497
498                  ns++;
499                 }
500                 else
501                 {
502                   PPU_status|=0x20;
503                   break;
504                 }
505          }
506         else
507          for(n=63;n>=0;n--,spr++)
508          {
509                 if((unsigned int)(scanline-spr->y)>=H) continue;
510
511                 if(ns<maxsprites)
512                 {
513                  if(n==63) sb=1;
514
515                  {
516                   SPRB dst;
517                   uint8 *C;
518                   int t;
519                   unsigned int vadr;
520
521                   t = (int)scanline-(spr->y);
522
523                   if (Sprite16)
524                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
525                   else
526                    vadr = (spr->no<<4)+vofs;
527
528                   if (spr->atr&V_FLIP)
529                   {
530                         vadr+=7;
531                         vadr-=t;
532                         vadr+=(P0&0x20)>>1;
533                         vadr-=t&8;
534                   }
535                   else
536                   {
537                         vadr+=t;
538                         vadr+=t&8;
539                   }
540
541                   if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
542                   else C = VRAMADR(vadr);
543                   dst.ca[0]=C[0];
544                   if(ns<8)
545                   {
546                    PPU_hook(0x2000);
547                    PPU_hook(vadr);
548                   }
549                   dst.ca[1]=C[8];
550                   dst.x=spr->x;
551                   dst.atr=spr->atr;
552
553
554                   *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
555                  }
556
557                  ns++;
558                 }
559                 else
560                 {
561                   PPU_status|=0x20;
562                   break;
563                 }
564          }
565         //if(ns>=7)
566         //printf("%d %d\n",scanline,ns);
567         if(ns>8) PPU_status|=0x20;      // Handle case when >8 sprites per
568 //                                 scanline option is enabled. 
569         else if(PPU_hook)
570         {
571          for(n=0;n<(8-ns);n++)
572          {
573                  PPU_hook(0x2000);
574                  PPU_hook(vofs);
575          }
576         }
577         numsprites=ns;
578         SpriteBlurp=sb;
579 }
580
581
582
583 void RefreshSprite(uint8 *target)
584 {
585       
586         int n,sprindex;
587         SPRB *spr;
588         uint8 *P=target;
589
590         //if (printed) {  printf("SPRB: %d  SPR: %d\n", sizeof(SPRB), sizeof(SPR)); printed=0; }
591         if(!numsprites) return;
592
593         FCEU_dwmemset(sprlinebuf,0x80808080,256);
594
595         numsprites--;
596         sprindex=numsprites;
597         spr = (SPRB*)SPRBUF;
598
599         //       for(n=nosprites;n>=0;n--,spr--)
600        for(n=numsprites;n>=0;n--,sprindex--)
601        {
602         uint8 J,atr,c1,c2;
603         int x=spr[sprindex].x;
604         uint8 *C;
605         uint8 *VB;
606                 
607         P+=x;
608
609         c1=((spr[sprindex].ca[0]>>1)&0x55)|(spr[sprindex].ca[1]&0xAA);
610         c2=(spr[sprindex].ca[0]&0x55)|((spr[sprindex].ca[1]<<1)&0xAA);
611
612         J=spr[sprindex].ca[0]|spr[sprindex].ca[1];
613         atr=spr[sprindex].atr;
614
615                        if(J)
616                        {        
617                         if(n==0 && SpriteBlurp && !(PPU_status&0x40))
618                         {  
619                          int z,ze=x+8;
620                          if(ze>256) {ze=256;}
621                          if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
622                          #ifdef FRAMESKIP
623                          || FSkip
624                          #endif
625                          ))
626                            // nothing wrong with this
627                          BGRender(target);
628
629                          if(!(atr&H_FLIP))
630                          {
631                           for(z=x;z<ze;z++)
632                           {
633                            if(J&(0x80>>(z-x)))
634                            {
635                             if(!(target[z]&64))
636                              tosprite=z;
637                            }
638                           }
639                          }
640                          else
641                          {
642                           for(z=x;z<ze;z++)
643                           {
644                            if(J&(1<<(z-x)))
645                            {
646                             if(!(target[z]&64))
647                              tosprite=z;
648                            }
649                           }
650                          }
651                          //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
652                         }
653
654          //C = sprlinebuf+(uint8)x;
655          C = &(sprlinebuf[(uint8)x]);
656          VB = (PALRAM+0x10)+((atr&3)<<2);
657
658          if(atr&SP_BACK) 
659          {
660           if (atr&H_FLIP)
661           {
662            if (J&0x02)  C[1]=VB[c1&3]|0x40;
663            if (J&0x01)  *C=VB[c2&3]|0x40;
664            c1>>=2;c2>>=2;
665            if (J&0x08)  C[3]=VB[c1&3]|0x40;
666            if (J&0x04)  C[2]=VB[c2&3]|0x40;
667            c1>>=2;c2>>=2;
668            if (J&0x20)  C[5]=VB[c1&3]|0x40;
669            if (J&0x10)  C[4]=VB[c2&3]|0x40;
670            c1>>=2;c2>>=2;
671            if (J&0x80)  C[7]=VB[c1]|0x40;
672            if (J&0x40)  C[6]=VB[c2]|0x40;
673           } else  {
674            if (J&0x02)  C[6]=VB[c1&3]|0x40;
675            if (J&0x01)  C[7]=VB[c2&3]|0x40;
676            c1>>=2;c2>>=2;
677            if (J&0x08)  C[4]=VB[c1&3]|0x40;
678            if (J&0x04)  C[5]=VB[c2&3]|0x40;
679            c1>>=2;c2>>=2;
680            if (J&0x20)  C[2]=VB[c1&3]|0x40;
681            if (J&0x10)  C[3]=VB[c2&3]|0x40;
682            c1>>=2;c2>>=2;
683            if (J&0x80)  *C=VB[c1]|0x40;
684            if (J&0x40)  C[1]=VB[c2]|0x40;
685           }
686          } else {
687           if (atr&H_FLIP)
688           {
689            if (J&0x02)  C[1]=VB[(c1&3)];
690            if (J&0x01)  *C=VB[(c2&3)];
691            c1>>=2;c2>>=2;
692            if (J&0x08)  C[3]=VB[(c1&3)];
693            if (J&0x04)  C[2]=VB[(c2&3)];
694            c1>>=2;c2>>=2;
695            if (J&0x20)  C[5]=VB[(c1&3)];
696            if (J&0x10)  C[4]=VB[(c2&3)];
697            c1>>=2;c2>>=2;
698            if (J&0x80)  C[7]=VB[c1];
699            if (J&0x40)  C[6]=VB[c2];
700           }else{                 
701            if (J&0x02)  C[6]=VB[(c1&3)];
702            if (J&0x01)  C[7]=VB[(c2&3)];
703            c1>>=2;c2>>=2;
704            if (J&0x08)  C[4]=VB[(c1&3)];
705            if (J&0x04)  C[5]=VB[(c2&3)];
706            c1>>=2;c2>>=2;
707            if (J&0x20)  C[2]=VB[(c1&3)];
708            if (J&0x10)  C[3]=VB[(c2&3)];
709            c1>>=2;c2>>=2;
710            if (J&0x80)  *C=VB[c1];
711            if (J&0x40)  C[1]=VB[c2];
712           }
713          }
714         }
715        P-=x;
716       }
717
718      numsprites=0;
719      #ifdef FRAMESKIP
720      if(FSkip) return;
721      #endif
722
723      {
724       uint8 n=((PPU[1]&4)^4)<<1;
725       loopskie:
726       {
727        uint32 t=*((uint32 *)(&(sprlinebuf[n])));
728        if(t!=0x80808080)
729        {
730         #ifdef LSB_FIRST
731         if(!(t&0x80))
732         {
733          if(!(t&0x40))       // Normal sprite
734           P[n]=sprlinebuf[n];
735          else if(P[n]&64)        // behind bg sprite
736           P[n]=sprlinebuf[n];
737         }
738
739         if(!(t&0x8000))
740         {
741          if(!(t&0x4000))       // Normal sprite
742           P[n+1]=(sprlinebuf+1)[n];
743          else if(P[n+1]&64)        // behind bg sprite
744           P[n+1]=(sprlinebuf+1)[n];
745         }
746
747         if(!(t&0x800000))
748         {
749          if(!(t&0x400000))       // Normal sprite
750           P[n+2]=(sprlinebuf+2)[n];
751          else if(P[n+2]&64)        // behind bg sprite
752           P[n+2]=(sprlinebuf+2)[n];
753         }
754
755         if(!(t&0x80000000))
756         {
757          if(!(t&0x40000000))       // Normal sprite
758           P[n+3]=(sprlinebuf+3)[n];
759          else if(P[n+3]&64)        // behind bg sprite
760           P[n+3]=(sprlinebuf+3)[n];
761         }
762         #else
763         if(!(t&0x80000000))
764         {
765          if(!(t&0x40))       // Normal sprite
766           P[n]=sprlinebuf[n];
767          else if(P[n]&64)        // behind bg sprite
768           P[n]=sprlinebuf[n];
769         }
770
771         if(!(t&0x800000))
772         {
773          if(!(t&0x4000))       // Normal sprite
774           P[n+1]=(sprlinebuf+1)[n];
775          else if(P[n+1]&64)        // behind bg sprite
776           P[n+1]=(sprlinebuf+1)[n];
777         }
778
779         if(!(t&0x8000))
780         {
781          if(!(t&0x400000))       // Normal sprite
782           P[n+2]=(sprlinebuf+2)[n];
783          else if(P[n+2]&64)        // behind bg sprite
784           P[n+2]=(sprlinebuf+2)[n];
785         }
786
787         if(!(t&0x80))
788         {
789          if(!(t&0x40000000))       // Normal sprite
790           P[n+3]=(sprlinebuf+3)[n];
791          else if(P[n+3]&64)        // behind bg sprite
792           P[n+3]=(sprlinebuf+3)[n];
793         }
794         #endif
795        }
796       }
797       n+=4;
798       if(n) goto loopskie;
799      }
800 }
801
802
803 */