frameskip, cleanups
[fceu.git] / ppu.c
... / ...
CommitLineData
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
36uint8 SPRAM[0x100];
37static uint8 SPRBUF[0x100];
38
39static uint8 sprlinebuf[256+8];
40extern void BGRender(uint8 *target);
41extern int tosprite;
42
43
44static int maxsprites=8;
45
46
47void FCEUI_DisableSpriteLimitation(int a)
48{
49 maxsprites=a?64:8;
50}
51
52
53//int printed=1;
54typedef struct {
55 uint8 y,no,atr,x;
56} SPR __attribute__((aligned(1)));
57
58typedef 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
68static uint8 nosprites,SpriteBlurp;
69
70void 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
200extern int FSkip;
201#endif
202
203void 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/*
432void 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
583void 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*/