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 |
36 | uint8 SPRAM[0x100] __attribute__ ((aligned (4))); |
37 | uint8 SPRBUF[0x100] __attribute__ ((aligned (4))); |
98733207 |
38 | |
6244011f |
39 | uint8 sprlinebuf[256+8] __attribute__ ((aligned (4))); |
e328100e |
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 | |
98733207 |
49 | extern void BGRender(uint8 *target); |
98733207 |
50 | |
51 | |
6244011f |
52 | int maxsprites=8; |
e328100e |
53 | static int sprlinebuf_empty=0; |
98733207 |
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 { |
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 | |
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 | |
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 |
224 | extern int FSkip; |
225 | #endif |
226 | |
e328100e |
227 | void 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 |
331 | void 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 | |