merge mapper code from FCEUX
[fceu.git] / ppu.c
CommitLineData
98733207 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
6244011f 36uint8 SPRAM[0x100] __attribute__ ((aligned (4)));
37uint8 SPRBUF[0x100] __attribute__ ((aligned (4)));
98733207 38
6244011f 39uint8 sprlinebuf[256+8] __attribute__ ((aligned (4)));
e328100e 40
41int32 sphitx;
42uint8 sphitdata;
43int 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
98733207 49extern void BGRender(uint8 *target);
98733207 50
51
6244011f 52int maxsprites=8;
e328100e 53static int sprlinebuf_empty=0;
98733207 54
55
56void FCEUI_DisableSpriteLimitation(int a)
57{
58 maxsprites=a?64:8;
59}
60
61
62//int printed=1;
63typedef struct {
64 uint8 y,no,atr,x;
65} SPR __attribute__((aligned(1)));
66
67typedef struct {
9115e7d2 68 // uint8 ca[2],atr,x;
69 uint8 ca[2],atr,x;
98733207 70 // union { int z; }
9115e7d2 71
98733207 72
73} SPRB __attribute__((aligned(1)));
74
75
76
77static uint8 nosprites,SpriteBlurp;
78
79void 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
9115e7d2 132
98733207 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];
ea80a45b 188 if(nosprites<8)
189 {
190 PPU_hook(0x2000);
191 PPU_hook(vadr);
192 }
98733207 193 dst.ca[1]=C[8];
98733207 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 }
ea80a45b 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
98733207 221}
222
223#ifdef FRAMESKIP
224extern int FSkip;
225#endif
226
e328100e 227void RefreshSprites(void)
98733207 228{
e328100e 229 int n;
98733207 230 SPRB *spr;
98733207 231
e328100e 232 spork=0;
98733207 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
98733207 247 nosprites--;
248 spr = (SPRB*)SPRBUF+nosprites;
249
e328100e 250 if (!sprlinebuf_empty)
251 {
252 FCEU_dwmemset(sprlinebuf,0x80808080,256);
253 sprlinebuf_empty = 1;
254 }
255
98733207 256 for(n=nosprites;n>=0;n--,spr--)
257 {
9115e7d2 258 register uint32 J;
98733207 259
260 J=spr->ca[0]|spr->ca[1];
98733207 261
9115e7d2 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
e328100e 270 if(n==0 && SpriteBlurp && !(PPU_status&0x40))
9115e7d2 271 {
e328100e 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);
98733207 283 }
284
e328100e 285
9115e7d2 286 c1=((spr->ca[0]>>1)&0x55)|(spr->ca[1]&0xAA);
287 c2=(spr->ca[0]&0x55)|((spr->ca[1]<<1)&0xAA);
288
98733207 289 C = sprlinebuf+x;
290 VB = (PALRAM+0x10)+((atr&3)<<2);
291
98733207 292 {
9115e7d2 293 J &= 0xff;
294 if(atr&SP_BACK) J |= 0x4000;
98733207 295 if (atr&H_FLIP)
296 {
9115e7d2 297 if (J&0x02) C[1]=VB[c1&3]|(J>>8);
298 if (J&0x01) *C=VB[c2&3]|(J>>8);
98733207 299 c1>>=2;c2>>=2;
9115e7d2 300 if (J&0x08) C[3]=VB[c1&3]|(J>>8);
301 if (J&0x04) C[2]=VB[c2&3]|(J>>8);
98733207 302 c1>>=2;c2>>=2;
9115e7d2 303 if (J&0x20) C[5]=VB[c1&3]|(J>>8);
304 if (J&0x10) C[4]=VB[c2&3]|(J>>8);
98733207 305 c1>>=2;c2>>=2;
9115e7d2 306 if (J&0x80) C[7]=VB[c1]|(J>>8);
307 if (J&0x40) C[6]=VB[c2]|(J>>8);
98733207 308 } else {
9115e7d2 309 if (J&0x02) C[6]=VB[c1&3]|(J>>8);
310 if (J&0x01) C[7]=VB[c2&3]|(J>>8);
98733207 311 c1>>=2;c2>>=2;
9115e7d2 312 if (J&0x08) C[4]=VB[c1&3]|(J>>8);
313 if (J&0x04) C[5]=VB[c2&3]|(J>>8);
98733207 314 c1>>=2;c2>>=2;
9115e7d2 315 if (J&0x20) C[2]=VB[c1&3]|(J>>8);
316 if (J&0x10) C[3]=VB[c2&3]|(J>>8);
98733207 317 c1>>=2;c2>>=2;
9115e7d2 318 if (J&0x80) *C=VB[c1]|(J>>8);
319 if (J&0x40) C[1]=VB[c2]|(J>>8);
98733207 320 }
98733207 321 }
e328100e 322 sprlinebuf_empty = 0;
98733207 323 }
9115e7d2 324 }
98733207 325
326 nosprites=0;
e328100e 327 spork=1;
328}
329
98733207 330
e328100e 331void CopySprites(uint8 *target)
332{
98733207 333 uint8 n=((PPU[1]&4)^4)<<1;
e328100e 334 //if ((int)n < minx) n = minx & 0xfc;
98733207 335 loopskie:
336 {
337 uint32 t=*(uint32 *)(sprlinebuf+n);
338 if(t!=0x80808080)
339 {
340 #ifdef LSB_FIRST
9115e7d2 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;
98733207 344 }
345
9115e7d2 346 if(!(t&0x00008000) && (!(t&0x00004000) || (tb&0x00004000))) {
347 tb &= ~0x0000ff00; tb |= t & 0x0000ff00;
98733207 348 }
349
9115e7d2 350 if(!(t&0x00800000) && (!(t&0x00400000) || (tb&0x00400000))) {
351 tb &= ~0x00ff0000; tb |= t & 0x00ff0000;
98733207 352 }
353
9115e7d2 354 if(!(t&0x80000000) && (!(t&0x40000000) || (tb&0x40000000))) {
355 tb &= ~0xff000000; tb |= t & 0xff000000;
98733207 356 }
9115e7d2 357 *(uint32 *)(target+n)=tb;
98733207 358 #else
e328100e 359 #error not implemented
98733207 360 #endif
361 }
362 }
363 n+=4;
364 if(n) goto loopskie;
98733207 365}
366
367