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);
189 *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
201 if(nosprites>8) PPU_status|=0x20; /* Handle case when >8 sprites per
202 scanline option is enabled. */
205 for(n=0;n<(8-nosprites);n++)
218 void RefreshSprite(uint8 *target)
223 if(!nosprites) return;
238 spr = (SPRB*)SPRBUF+nosprites;
240 for(n=nosprites;n>=0;n--,spr--)
244 J=spr->ca[0]|spr->ca[1];
248 register uint8 atr,c1,c2;
256 if (minx == 256) FCEU_dwmemset(sprlinebuf,0x80808080,256); // only clear sprite buff when we encounter first sprite
259 if(n==0 && SpriteBlurp && !(PPU_status&0x40))
263 if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
292 //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
295 c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
296 c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
299 VB = (PALRAM+0x10)+((atr&3)<<2);
303 if(atr&SP_BACK) J |= 0x4000;
306 if (J&0x02) C[1]=VB[c1&3]|(J>>8);
307 if (J&0x01) *C=VB[c2&3]|(J>>8);
309 if (J&0x08) C[3]=VB[c1&3]|(J>>8);
310 if (J&0x04) C[2]=VB[c2&3]|(J>>8);
312 if (J&0x20) C[5]=VB[c1&3]|(J>>8);
313 if (J&0x10) C[4]=VB[c2&3]|(J>>8);
315 if (J&0x80) C[7]=VB[c1]|(J>>8);
316 if (J&0x40) C[6]=VB[c2]|(J>>8);
318 if (J&0x02) C[6]=VB[c1&3]|(J>>8);
319 if (J&0x01) C[7]=VB[c2&3]|(J>>8);
321 if (J&0x08) C[4]=VB[c1&3]|(J>>8);
322 if (J&0x04) C[5]=VB[c2&3]|(J>>8);
324 if (J&0x20) C[2]=VB[c1&3]|(J>>8);
325 if (J&0x10) C[3]=VB[c2&3]|(J>>8);
327 if (J&0x80) *C=VB[c1]|(J>>8);
328 if (J&0x40) C[1]=VB[c2]|(J>>8);
338 if (minx == 256) return; // no visible sprites
341 uint8 n=((PPU[1]&4)^4)<<1;
342 if ((int)n < minx) n = minx & 0xfc;
345 uint32 t=*(uint32 *)(sprlinebuf+n);
349 uint32 tb=*(uint32 *)(target+n);
350 if(!(t&0x00000080) && (!(t&0x00000040) || (tb&0x00000040))) { // have sprite pixel AND (normal sprite OR behind bg with no bg)
351 tb &= ~0x000000ff; tb |= t & 0x000000ff;
354 if(!(t&0x00008000) && (!(t&0x00004000) || (tb&0x00004000))) {
355 tb &= ~0x0000ff00; tb |= t & 0x0000ff00;
358 if(!(t&0x00800000) && (!(t&0x00400000) || (tb&0x00400000))) {
359 tb &= ~0x00ff0000; tb |= t & 0x00ff0000;
362 if(!(t&0x80000000) && (!(t&0x40000000) || (tb&0x40000000))) {
363 tb &= ~0xff000000; tb |= t & 0xff000000;
365 *(uint32 *)(target+n)=tb;
369 if(!(t&0x40)) // Normal sprite
371 else if(P[n]&64) // behind bg sprite
377 if(!(t&0x4000)) // Normal sprite
378 P[n+1]=(sprlinebuf+1)[n];
379 else if(P[n+1]&64) // behind bg sprite
380 P[n+1]=(sprlinebuf+1)[n];
385 if(!(t&0x400000)) // Normal sprite
386 P[n+2]=(sprlinebuf+2)[n];
387 else if(P[n+2]&64) // behind bg sprite
388 P[n+2]=(sprlinebuf+2)[n];
393 if(!(t&0x40000000)) // Normal sprite
394 P[n+3]=(sprlinebuf+3)[n];
395 else if(P[n+3]&64) // behind bg sprite
396 P[n+3]=(sprlinebuf+3)[n];
411 void FetchSpriteData(void)
426 vofs=(unsigned int)(P0&0x8&(((P0&0x20)^0x20)>>2))<<9;
430 for(n=63;n>=0;n--,spr++)
432 if((unsigned int)(scanline-spr->y)>=H) continue;
433 //printf("%d, %u\n",scanline,(unsigned int)(scanline-spr->y));
444 t = (int)scanline-(spr->y);
447 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
449 vadr = (spr->no<<4)+vofs;
464 // Fix this geniestage hack
465 if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
466 else C = VRAMADR(vadr);
474 *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
486 for(n=63;n>=0;n--,spr++)
488 if((unsigned int)(scanline-spr->y)>=H) continue;
500 t = (int)scanline-(spr->y);
503 vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
505 vadr = (spr->no<<4)+vofs;
520 if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
521 else C = VRAMADR(vadr);
533 *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
545 //printf("%d %d\n",scanline,ns);
546 if(ns>8) PPU_status|=0x20; // Handle case when >8 sprites per
547 // scanline option is enabled.
550 for(n=0;n<(8-ns);n++)
562 void RefreshSprite(uint8 *target)
569 //if (printed) { printf("SPRB: %d SPR: %d\n", sizeof(SPRB), sizeof(SPR)); printed=0; }
570 if(!numsprites) return;
572 FCEU_dwmemset(sprlinebuf,0x80808080,256);
578 // for(n=nosprites;n>=0;n--,spr--)
579 for(n=numsprites;n>=0;n--,sprindex--)
582 int x=spr[sprindex].x;
588 c1=((spr[sprindex].ca[0]>>1)&0x55)|(spr[sprindex].ca[1]&0xAA);
589 c2=(spr[sprindex].ca[0]&0x55)|((spr[sprindex].ca[1]<<1)&0xAA);
591 J=spr[sprindex].ca[0]|spr[sprindex].ca[1];
592 atr=spr[sprindex].atr;
596 if(n==0 && SpriteBlurp && !(PPU_status&0x40))
600 if(ScreenON && (scanline<FSettings.FirstSLine || scanline>FSettings.LastSLine
605 // nothing wrong with this
630 //FCEU_DispMessage("%d, %d:%d",scanline,x,tosprite);
633 //C = sprlinebuf+(uint8)x;
634 C = &(sprlinebuf[(uint8)x]);
635 VB = (PALRAM+0x10)+((atr&3)<<2);
641 if (J&0x02) C[1]=VB[c1&3]|0x40;
642 if (J&0x01) *C=VB[c2&3]|0x40;
644 if (J&0x08) C[3]=VB[c1&3]|0x40;
645 if (J&0x04) C[2]=VB[c2&3]|0x40;
647 if (J&0x20) C[5]=VB[c1&3]|0x40;
648 if (J&0x10) C[4]=VB[c2&3]|0x40;
650 if (J&0x80) C[7]=VB[c1]|0x40;
651 if (J&0x40) C[6]=VB[c2]|0x40;
653 if (J&0x02) C[6]=VB[c1&3]|0x40;
654 if (J&0x01) C[7]=VB[c2&3]|0x40;
656 if (J&0x08) C[4]=VB[c1&3]|0x40;
657 if (J&0x04) C[5]=VB[c2&3]|0x40;
659 if (J&0x20) C[2]=VB[c1&3]|0x40;
660 if (J&0x10) C[3]=VB[c2&3]|0x40;
662 if (J&0x80) *C=VB[c1]|0x40;
663 if (J&0x40) C[1]=VB[c2]|0x40;
668 if (J&0x02) C[1]=VB[(c1&3)];
669 if (J&0x01) *C=VB[(c2&3)];
671 if (J&0x08) C[3]=VB[(c1&3)];
672 if (J&0x04) C[2]=VB[(c2&3)];
674 if (J&0x20) C[5]=VB[(c1&3)];
675 if (J&0x10) C[4]=VB[(c2&3)];
677 if (J&0x80) C[7]=VB[c1];
678 if (J&0x40) C[6]=VB[c2];
680 if (J&0x02) C[6]=VB[(c1&3)];
681 if (J&0x01) C[7]=VB[(c2&3)];
683 if (J&0x08) C[4]=VB[(c1&3)];
684 if (J&0x04) C[5]=VB[(c2&3)];
686 if (J&0x20) C[2]=VB[(c1&3)];
687 if (J&0x10) C[3]=VB[(c2&3)];
689 if (J&0x80) *C=VB[c1];
690 if (J&0x40) C[1]=VB[c2];
703 uint8 n=((PPU[1]&4)^4)<<1;
706 uint32 t=*((uint32 *)(&(sprlinebuf[n])));
712 if(!(t&0x40)) // Normal sprite
714 else if(P[n]&64) // behind bg sprite
720 if(!(t&0x4000)) // Normal sprite
721 P[n+1]=(sprlinebuf+1)[n];
722 else if(P[n+1]&64) // behind bg sprite
723 P[n+1]=(sprlinebuf+1)[n];
728 if(!(t&0x400000)) // Normal sprite
729 P[n+2]=(sprlinebuf+2)[n];
730 else if(P[n+2]&64) // behind bg sprite
731 P[n+2]=(sprlinebuf+2)[n];
736 if(!(t&0x40000000)) // Normal sprite
737 P[n+3]=(sprlinebuf+3)[n];
738 else if(P[n+3]&64) // behind bg sprite
739 P[n+3]=(sprlinebuf+3)[n];
744 if(!(t&0x40)) // Normal sprite
746 else if(P[n]&64) // behind bg sprite
752 if(!(t&0x4000)) // Normal sprite
753 P[n+1]=(sprlinebuf+1)[n];
754 else if(P[n+1]&64) // behind bg sprite
755 P[n+1]=(sprlinebuf+1)[n];
760 if(!(t&0x400000)) // Normal sprite
761 P[n+2]=(sprlinebuf+2)[n];
762 else if(P[n+2]&64) // behind bg sprite
763 P[n+2]=(sprlinebuf+2)[n];
768 if(!(t&0x40000000)) // Normal sprite
769 P[n+3]=(sprlinebuf+3)[n];
770 else if(P[n+3]&64) // behind bg sprite
771 P[n+3]=(sprlinebuf+3)[n];