gp2x_test added, cli removed
[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 uint8 sprlinebuf[256+8];
40
41 int32 sphitx;
42 uint8 sphitdata;
43 int spork=0;            /* spork the world.  Any sprites on this line?
44                            Then this will be set to 1.  Needed for zapper
45                            emulation and *gasp* sprite emulation.
46                         */
47
48
49 extern void BGRender(uint8 *target);
50
51
52 static int maxsprites=8;
53 static int sprlinebuf_empty=0;
54
55
56 void FCEUI_DisableSpriteLimitation(int a)
57 {
58  maxsprites=a?64:8;
59 }
60
61
62 //int printed=1;
63 typedef struct {
64         uint8 y,no,atr,x;
65 } SPR __attribute__((aligned(1)));
66
67 typedef struct {
68   //    uint8 ca[2],atr,x;
69         uint8 ca[2],atr,x;
70   //  union {  int z; }
71
72
73 } SPRB __attribute__((aligned(1)));
74
75
76
77 static uint8 nosprites,SpriteBlurp;
78
79 void FetchSpriteData(void)
80 {
81         SPR *spr;
82         uint8 H;
83         int n,vofs;
84
85         spr=(SPR *)SPRAM;
86         H=8;
87
88         nosprites=SpriteBlurp=0;
89
90         vofs=(unsigned int)(PPU[0]&0x8&(((PPU[0]&0x20)^0x20)>>2))<<9;
91         H+=(PPU[0]&0x20)>>2;
92
93         if(!PPU_hook)
94          for(n=63;n>=0;n--,spr++)
95          {
96                 if((unsigned int)(scanline-spr->y)>=H) continue;
97
98                 if(nosprites<maxsprites)
99                 {
100                  if(n==63) SpriteBlurp=1;
101
102                  {
103                   SPRB dst;
104                   uint8 *C;
105                   int t;
106                   unsigned int vadr;
107
108                   t = (int)scanline-(spr->y);
109
110                   if (Sprite16)
111                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
112                   else
113                    vadr = (spr->no<<4)+vofs;
114
115                   if (spr->atr&V_FLIP)
116                   {
117                         vadr+=7;
118                         vadr-=t;
119                         vadr+=(PPU[0]&0x20)>>1;
120                         vadr-=t&8;
121                   }
122                   else
123                   {
124                         vadr+=t;
125                         vadr+=t&8;
126                   }
127
128                   /* Fix this geniestage hack */
129                   if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
130                   else C = VRAMADR(vadr);
131
132
133                   dst.ca[0]=C[0];
134                   dst.ca[1]=C[8];
135                   dst.x=spr->x;
136                   dst.atr=spr->atr;
137
138
139                   *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
140                  }
141
142                  nosprites++;
143                 }
144                 else
145                 {
146                   PPU_status|=0x20;
147                   break;
148                 }
149          }
150         else
151          for(n=63;n>=0;n--,spr++)
152          {
153                 if((unsigned int)(scanline-spr->y)>=H) continue;
154
155                 if(nosprites<maxsprites)
156                 {
157                  if(n==63) SpriteBlurp=1;
158
159                  {
160                   SPRB dst;
161                   uint8 *C;
162                   int t;
163                   unsigned int vadr;
164
165                   t = (int)scanline-(spr->y);
166
167                   if (Sprite16)
168                    vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
169                   else
170                    vadr = (spr->no<<4)+vofs;
171
172                   if (spr->atr&V_FLIP)
173                   {
174                         vadr+=7;
175                         vadr-=t;
176                         vadr+=(PPU[0]&0x20)>>1;
177                         vadr-=t&8;
178                   }
179                   else
180                   {
181                         vadr+=t;
182                         vadr+=t&8;
183                   }
184
185                   if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
186                   else C = VRAMADR(vadr);
187                   dst.ca[0]=C[0];
188                   if(nosprites<8)
189                   {
190                    PPU_hook(0x2000);
191                    PPU_hook(vadr);
192                   }
193                   dst.ca[1]=C[8];
194                   dst.x=spr->x;
195                   dst.atr=spr->atr;
196
197
198                   *(uint32 *)&SPRBUF[nosprites<<2]=*(uint32 *)&dst;
199                  }
200
201                  nosprites++;
202                 }
203                 else
204                 {
205                   PPU_status|=0x20;
206                   break;
207                 }
208          }
209
210         if(nosprites>8) PPU_status|=0x20;  /* Handle case when >8 sprites per
211                                            scanline option is enabled. */
212         else if(PPU_hook)
213         {
214          for(n=0;n<(8-nosprites);n++)
215          {
216                  PPU_hook(0x2000);
217                  PPU_hook(vofs);
218          }
219         }
220
221 }
222
223 #ifdef FRAMESKIP
224 extern int FSkip;
225 #endif
226
227 void RefreshSprites(void)
228 {
229         int n;
230         SPRB *spr;
231
232         spork=0;
233         if(!nosprites) return;
234         #ifdef FRAMESKIP
235         if(FSkip)
236         {
237          if(!SpriteBlurp)
238          {
239           nosprites=0;
240           return;
241          }
242          else
243           nosprites=1;
244         }
245         #endif
246
247         nosprites--;
248         spr = (SPRB*)SPRBUF+nosprites;
249
250        if (!sprlinebuf_empty)
251        {
252         FCEU_dwmemset(sprlinebuf,0x80808080,256);
253         sprlinebuf_empty = 1;
254        }
255
256        for(n=nosprites;n>=0;n--,spr--)
257        {
258         register uint32 J;
259
260         J=spr->ca[0]|spr->ca[1];
261
262         if (J)
263         {
264           register uint8 atr,c1,c2;
265           uint8 *C;
266           uint8 *VB;
267           int x=spr->x;
268           atr=spr->atr;
269
270                         if(n==0 && SpriteBlurp && !(PPU_status&0x40))
271                         {
272                          sphitx=x;
273                          sphitdata=J;
274                          if(atr&H_FLIP)
275                           sphitdata=    ((J<<7)&0x80) |
276                                         ((J<<5)&0x40) |
277                                         ((J<<3)&0x20) |
278                                         ((J<<1)&0x10) |
279                                         ((J>>1)&0x08) |
280                                         ((J>>3)&0x04) |
281                                         ((J>>5)&0x02) |
282                                         ((J>>7)&0x01);
283                         }
284
285
286          c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
287          c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
288
289          C = sprlinebuf+x;
290          VB = (PALRAM+0x10)+((atr&3)<<2);
291
292          {
293           J &= 0xff;
294           if(atr&SP_BACK) J |= 0x4000;
295           if (atr&H_FLIP)
296           {
297            if (J&0x02)  C[1]=VB[c1&3]|(J>>8);
298            if (J&0x01)  *C=VB[c2&3]|(J>>8);
299            c1>>=2;c2>>=2;
300            if (J&0x08)  C[3]=VB[c1&3]|(J>>8);
301            if (J&0x04)  C[2]=VB[c2&3]|(J>>8);
302            c1>>=2;c2>>=2;
303            if (J&0x20)  C[5]=VB[c1&3]|(J>>8);
304            if (J&0x10)  C[4]=VB[c2&3]|(J>>8);
305            c1>>=2;c2>>=2;
306            if (J&0x80)  C[7]=VB[c1]|(J>>8);
307            if (J&0x40)  C[6]=VB[c2]|(J>>8);
308           } else  {
309            if (J&0x02)  C[6]=VB[c1&3]|(J>>8);
310            if (J&0x01)  C[7]=VB[c2&3]|(J>>8);
311            c1>>=2;c2>>=2;
312            if (J&0x08)  C[4]=VB[c1&3]|(J>>8);
313            if (J&0x04)  C[5]=VB[c2&3]|(J>>8);
314            c1>>=2;c2>>=2;
315            if (J&0x20)  C[2]=VB[c1&3]|(J>>8);
316            if (J&0x10)  C[3]=VB[c2&3]|(J>>8);
317            c1>>=2;c2>>=2;
318            if (J&0x80)  *C=VB[c1]|(J>>8);
319            if (J&0x40)  C[1]=VB[c2]|(J>>8);
320           }
321          }
322          sprlinebuf_empty = 0;
323       }
324      }
325
326      nosprites=0;
327      spork=1;
328 }
329
330
331 void CopySprites(uint8 *target)
332 {
333       uint8 n=((PPU[1]&4)^4)<<1;
334       //if ((int)n < minx) n = minx & 0xfc;
335       loopskie:
336       {
337        uint32 t=*(uint32 *)(sprlinebuf+n);
338        if(t!=0x80808080)
339        {
340         #ifdef LSB_FIRST
341         uint32 tb=*(uint32 *)(target+n);
342         if(!(t&0x00000080) && (!(t&0x00000040) || (tb&0x00000040))) { // have sprite pixel AND (normal sprite OR behind bg with no bg)
343           tb &= ~0x000000ff; tb |= t & 0x000000ff;
344         }
345
346         if(!(t&0x00008000) && (!(t&0x00004000) || (tb&0x00004000))) {
347           tb &= ~0x0000ff00; tb |= t & 0x0000ff00;
348         }
349
350         if(!(t&0x00800000) && (!(t&0x00400000) || (tb&0x00400000))) {
351           tb &= ~0x00ff0000; tb |= t & 0x00ff0000;
352         }
353
354         if(!(t&0x80000000) && (!(t&0x40000000) || (tb&0x40000000))) {
355           tb &= ~0xff000000; tb |= t & 0xff000000;
356         }
357         *(uint32 *)(target+n)=tb;
358         #else
359         #error not implemented
360         #endif
361        }
362       }
363       n+=4;
364       if(n) goto loopskie;
365 }
366
367