2 * For whatever reason, breaking this out of fce.c made sprites not corrupt
28 #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
29 //#define MMC5BGVRAMADR(V) &MMC5BGVPage[(V)>>10][(V)]
30 #define VRAMADR(V) &VPage[(V)>>10][(V)]
37 static uint8 SPRBUF[0x100];
39 static uint8 sprlinebuf[256+8];
40 extern void BGRender(uint8 *target);
44 static int maxsprites=8;
47 void FCEUI_DisableSpriteLimitation(int a)
56 } SPR __attribute__((aligned(1)));
64 } SPRB __attribute__((aligned(1)));
68 static uint8 nosprites,SpriteBlurp;
70 void FetchSpriteData(void)
79 nosprites=SpriteBlurp=0;
81 vofs=(unsigned int)(PPU[0]&0x8&(((PPU[0]&0x20)^0x20)>>2))<<9;
85 for(n=63;n>=0;n--,spr++)
87 if((unsigned int)(scanline-spr->y)>=H) continue;
89 if(nosprites<maxsprites)
91 if(n==63) SpriteBlurp=1;
99 t = (int)scanline-(spr->y);
102 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
104 vadr = (spr->no<<4)+vofs;
110 vadr+=(PPU[0]&0x20)>>1;
119 /* Fix this geniestage hack */
120 if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
121 else C = VRAMADR(vadr);
130 *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
142 for(n=63;n>=0;n--,spr++)
144 if((unsigned int)(scanline-spr->y)>=H) continue;
146 if(nosprites<maxsprites)
148 if(n==63) SpriteBlurp=1;
156 t = (int)scanline-(spr->y);
159 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
161 vadr = (spr->no<<4)+vofs;
167 vadr+=(PPU[0]&0x20)>>1;
176 if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
177 else C = VRAMADR(vadr);
186 *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
203 void RefreshSprite(uint8 *target)
208 if(!nosprites) return;
223 spr = (SPRB*)SPRBUF+nosprites;
225 for(n=nosprites;n>=0;n--,spr--)
229 J=spr->ca[0]|spr->ca[1];
233 register uint8 atr,c1,c2;
241 if (minx == 256) FCEU_dwmemset(sprlinebuf,0x80808080,256); // only clear sprite buff when we encounter first sprite
244 if(n==0 && SpriteBlurp && !(PPU_status&0x40))
248 if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
277 //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
280 c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
281 c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
284 VB = (PALRAM+0x10)+((atr&3)<<2);
288 if(atr&SP_BACK) J |= 0x4000;
291 if (J&0x02) C[1]=VB[c1&3]|(J>>8);
292 if (J&0x01) *C=VB[c2&3]|(J>>8);
294 if (J&0x08) C[3]=VB[c1&3]|(J>>8);
295 if (J&0x04) C[2]=VB[c2&3]|(J>>8);
297 if (J&0x20) C[5]=VB[c1&3]|(J>>8);
298 if (J&0x10) C[4]=VB[c2&3]|(J>>8);
300 if (J&0x80) C[7]=VB[c1]|(J>>8);
301 if (J&0x40) C[6]=VB[c2]|(J>>8);
303 if (J&0x02) C[6]=VB[c1&3]|(J>>8);
304 if (J&0x01) C[7]=VB[c2&3]|(J>>8);
306 if (J&0x08) C[4]=VB[c1&3]|(J>>8);
307 if (J&0x04) C[5]=VB[c2&3]|(J>>8);
309 if (J&0x20) C[2]=VB[c1&3]|(J>>8);
310 if (J&0x10) C[3]=VB[c2&3]|(J>>8);
312 if (J&0x80) *C=VB[c1]|(J>>8);
313 if (J&0x40) C[1]=VB[c2]|(J>>8);
323 if (minx == 256) return; // no visible sprites
326 uint8 n=((PPU[1]&4)^4)<<1;
327 if ((int)n < minx) n = minx & 0xfc;
330 uint32 t=*(uint32 *)(sprlinebuf+n);
334 uint32 tb=*(uint32 *)(target+n);
335 if(!(t&0x00000080) && (!(t&0x00000040) || (tb&0x00000040))) { // have sprite pixel AND (normal sprite OR behind bg with no bg)
336 tb &= ~0x000000ff; tb |= t & 0x000000ff;
339 if(!(t&0x00008000) && (!(t&0x00004000) || (tb&0x00004000))) {
340 tb &= ~0x0000ff00; tb |= t & 0x0000ff00;
343 if(!(t&0x00800000) && (!(t&0x00400000) || (tb&0x00400000))) {
344 tb &= ~0x00ff0000; tb |= t & 0x00ff0000;
347 if(!(t&0x80000000) && (!(t&0x40000000) || (tb&0x40000000))) {
348 tb &= ~0xff000000; tb |= t & 0xff000000;
350 *(uint32 *)(target+n)=tb;
354 if(!(t&0x40)) // Normal sprite
356 else if(P[n]&64) // behind bg sprite
362 if(!(t&0x4000)) // Normal sprite
363 P[n+1]=(sprlinebuf+1)[n];
364 else if(P[n+1]&64) // behind bg sprite
365 P[n+1]=(sprlinebuf+1)[n];
370 if(!(t&0x400000)) // Normal sprite
371 P[n+2]=(sprlinebuf+2)[n];
372 else if(P[n+2]&64) // behind bg sprite
373 P[n+2]=(sprlinebuf+2)[n];
378 if(!(t&0x40000000)) // Normal sprite
379 P[n+3]=(sprlinebuf+3)[n];
380 else if(P[n+3]&64) // behind bg sprite
381 P[n+3]=(sprlinebuf+3)[n];
396 void FetchSpriteData(void)
411 vofs=(unsigned int)(P0&0x8&(((P0&0x20)^0x20)>>2))<<9;
415 for(n=63;n>=0;n--,spr++)
417 if((unsigned int)(scanline-spr->y)>=H) continue;
418 //printf("%d, %u\n",scanline,(unsigned int)(scanline-spr->y));
429 t = (int)scanline-(spr->y);
432 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
434 vadr = (spr->no<<4)+vofs;
449 // Fix this geniestage hack
450 if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
451 else C = VRAMADR(vadr);
459 *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
471 for(n=63;n>=0;n--,spr++)
473 if((unsigned int)(scanline-spr->y)>=H) continue;
485 t = (int)scanline-(spr->y);
488 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
490 vadr = (spr->no<<4)+vofs;
505 if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
506 else C = VRAMADR(vadr);
518 *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
530 //printf("%d %d\n",scanline,ns);
531 if(ns>8) PPU_status|=0x20; // Handle case when >8 sprites per
532 // scanline option is enabled.
535 for(n=0;n<(8-ns);n++)
547 void RefreshSprite(uint8 *target)
554 //if (printed) { printf("SPRB: %d SPR: %d\n", sizeof(SPRB), sizeof(SPR)); printed=0; }
555 if(!numsprites) return;
557 FCEU_dwmemset(sprlinebuf,0x80808080,256);
563 // for(n=nosprites;n>=0;n--,spr--)
564 for(n=numsprites;n>=0;n--,sprindex--)
567 int x=spr[sprindex].x;
573 c1=((spr[sprindex].ca[0]>>1)&0x55)|(spr[sprindex].ca[1]&0xAA);
574 c2=(spr[sprindex].ca[0]&0x55)|((spr[sprindex].ca[1]<<1)&0xAA);
576 J=spr[sprindex].ca[0]|spr[sprindex].ca[1];
577 atr=spr[sprindex].atr;
581 if(n==0 && SpriteBlurp && !(PPU_status&0x40))
585 if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
590 // nothing wrong with this
615 //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
618 //C = sprlinebuf+(uint8)x;
619 C = &(sprlinebuf[(uint8)x]);
620 VB = (PALRAM+0x10)+((atr&3)<<2);
626 if (J&0x02) C[1]=VB[c1&3]|0x40;
627 if (J&0x01) *C=VB[c2&3]|0x40;
629 if (J&0x08) C[3]=VB[c1&3]|0x40;
630 if (J&0x04) C[2]=VB[c2&3]|0x40;
632 if (J&0x20) C[5]=VB[c1&3]|0x40;
633 if (J&0x10) C[4]=VB[c2&3]|0x40;
635 if (J&0x80) C[7]=VB[c1]|0x40;
636 if (J&0x40) C[6]=VB[c2]|0x40;
638 if (J&0x02) C[6]=VB[c1&3]|0x40;
639 if (J&0x01) C[7]=VB[c2&3]|0x40;
641 if (J&0x08) C[4]=VB[c1&3]|0x40;
642 if (J&0x04) C[5]=VB[c2&3]|0x40;
644 if (J&0x20) C[2]=VB[c1&3]|0x40;
645 if (J&0x10) C[3]=VB[c2&3]|0x40;
647 if (J&0x80) *C=VB[c1]|0x40;
648 if (J&0x40) C[1]=VB[c2]|0x40;
653 if (J&0x02) C[1]=VB[(c1&3)];
654 if (J&0x01) *C=VB[(c2&3)];
656 if (J&0x08) C[3]=VB[(c1&3)];
657 if (J&0x04) C[2]=VB[(c2&3)];
659 if (J&0x20) C[5]=VB[(c1&3)];
660 if (J&0x10) C[4]=VB[(c2&3)];
662 if (J&0x80) C[7]=VB[c1];
663 if (J&0x40) C[6]=VB[c2];
665 if (J&0x02) C[6]=VB[(c1&3)];
666 if (J&0x01) C[7]=VB[(c2&3)];
668 if (J&0x08) C[4]=VB[(c1&3)];
669 if (J&0x04) C[5]=VB[(c2&3)];
671 if (J&0x20) C[2]=VB[(c1&3)];
672 if (J&0x10) C[3]=VB[(c2&3)];
674 if (J&0x80) *C=VB[c1];
675 if (J&0x40) C[1]=VB[c2];
688 uint8 n=((PPU[1]&4)^4)<<1;
691 uint32 t=*((uint32 *)(&(sprlinebuf[n])));
697 if(!(t&0x40)) // Normal sprite
699 else if(P[n]&64) // behind bg sprite
705 if(!(t&0x4000)) // Normal sprite
706 P[n+1]=(sprlinebuf+1)[n];
707 else if(P[n+1]&64) // behind bg sprite
708 P[n+1]=(sprlinebuf+1)[n];
713 if(!(t&0x400000)) // Normal sprite
714 P[n+2]=(sprlinebuf+2)[n];
715 else if(P[n+2]&64) // behind bg sprite
716 P[n+2]=(sprlinebuf+2)[n];
721 if(!(t&0x40000000)) // Normal sprite
722 P[n+3]=(sprlinebuf+3)[n];
723 else if(P[n+3]&64) // behind bg sprite
724 P[n+3]=(sprlinebuf+3)[n];
729 if(!(t&0x40)) // Normal sprite
731 else if(P[n]&64) // behind bg sprite
737 if(!(t&0x4000)) // Normal sprite
738 P[n+1]=(sprlinebuf+1)[n];
739 else if(P[n+1]&64) // behind bg sprite
740 P[n+1]=(sprlinebuf+1)[n];
745 if(!(t&0x400000)) // Normal sprite
746 P[n+2]=(sprlinebuf+2)[n];
747 else if(P[n+2]&64) // behind bg sprite
748 P[n+2]=(sprlinebuf+2)[n];
753 if(!(t&0x40000000)) // Normal sprite
754 P[n+3]=(sprlinebuf+3)[n];
755 else if(P[n+3]&64) // behind bg sprite
756 P[n+3]=(sprlinebuf+3)[n];