Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snem/ppu.c
28515 views
1
#include <stdio.h>
2
#include "snes.h"
3
/*struct
4
{*/
5
unsigned char ppu_vidportc,ppu_sdr;
6
unsigned char ppu_main,ppu_sub;
7
unsigned char *ppu_vram;
8
unsigned short *ppu_vramw;
9
unsigned short ppu_vaddr;
10
unsigned short ppu_bg[4],ppu_chr[4];
11
int ppu_xs[4],ppu_ys[4];
12
int ppu_vinc,ppu_mode;
13
unsigned short ppu_cgramaddr;
14
unsigned short ppu_cgram[256];
15
uint32 ppu_palette[256];
16
int ppu_paldirty[256];
17
uint32 ppu_coltable[8],ppu_coltable16[8];
18
uint32 ppu_bittable[2][16],ppu_masktable[2][16];
19
int ppu_firstread;
20
uint32 ppu_wramaddr;
21
unsigned char ppu_cgwsel,ppu_cgadsub;
22
uint32 ppu_fixedcol;
23
int ppu_fgcount,ppu_fgmask,ppu_fgshift;
24
unsigned char ppu_wobjsel;
25
int ppu_w1l,ppu_w1r,ppu_w2l,ppu_w2r;
26
/*} ppu;*/
27
28
29
struct
30
{
31
int screenon;
32
int mainena,subena;
33
int bg3pri;
34
int xs[4],ys[4];
35
int tsize[4],xsize[4],ysize[4];
36
int w1l,w1r,w2l,w2r;
37
#ifdef MODE7
38
uint32 fixedcol;
39
int bright;
40
unsigned short m7a,m7b,m7c,m7d,m7x,m7y;
41
int m7change;
42
unsigned char m7sel;
43
unsigned char mosaic,mena;
44
unsigned char cgwsel,cgadsub;
45
int wchg;
46
unsigned char wobjsel;
47
#endif
48
} lines[224];
49
int lines_mode[224];
50
int lines_mask[224];
51
unsigned short lines_chr[224][4];
52
unsigned short lines_bg[224][4];
53
54
unsigned short objnamesel;
55
unsigned char window[3][256];
56
int wobjlog;
57
uint32 ppufc;
58
59
unsigned char mosaic;
60
int rescan[4];
61
unsigned short sobjaddr;
62
int curframe=0;
63
int fpsc;
64
65
int prioritybuffer[4][2];
66
/*Tile caching system*/
67
uint32 tiless[4096][2][8][2];
68
69
char tiledatm[4096][8];
70
char tileupdate[4096];
71
72
void updatetiles()
73
{
74
int c,y;
75
for (c=0; c<4096; c++)
76
{
77
if (tileupdate[c])
78
{
79
for (y=0; y<8; y++)
80
{
81
tiless[c][0][y][0]=ppu_bittable[0][ppu_vram[(c<<4)|(y<<1)]>>4]
82
|(ppu_bittable[0][ppu_vram[(c<<4)|(y<<1)|1]>>4]<<1);
83
tiless[c][0][y][1]=ppu_bittable[0][ppu_vram[(c<<4)|(y<<1)]&15]|(ppu_bittable[0][ppu_vram[(c<<4)|(y<<1)|1]&15]<<1);
84
tiless[c][1][y][0]=ppu_bittable[1][ppu_vram[(c<<4)|(y<<1)]>>4]|(ppu_bittable[1][ppu_vram[(c<<4)|(y<<1)|1]>>4]<<1);
85
tiless[c][1][y][1]=ppu_bittable[1][ppu_vram[(c<<4)|(y<<1)]&15]|(ppu_bittable[1][ppu_vram[(c<<4)|(y<<1)|1]&15]<<1);
86
if (tiless[c][0][y][0]|tiless[c][0][y][1]) tiledatm[c][y]=1;
87
else tiledatm[c][y]=0;
88
}
89
tileupdate[c]=0;
90
}
91
}
92
}
93
94
int sblankchk;
95
int spcemu,palf,soundupdate;
96
unsigned char *ram;
97
int lastsetzf=1;
98
int ymode[4],xsize[4],bgdat[4];
99
uint32 matrixr;
100
#ifdef MODE7
101
unsigned short m7a,m7b;
102
#endif
103
int objsize[4]= {1,1,2,2};
104
int objsizes[16][2]= { {1,1}, {2,2}, {1,1}, {4,4}, {1,1}, {8,8}, {2,2}, {4,4}, {2,2}, {8,8}, {4,4}, {8,8} };
105
106
struct
107
{
108
int x[128],y[128],xs[128],ys[128];
109
int hf[128],vf[128],p[128],sx[128],sy[128];
110
unsigned short t[128];
111
uint32 c[128];
112
} sprites;
113
114
uint32 hmostable[256];
115
unsigned char fliptable[256];
116
#ifdef MODE7
117
unsigned short m7a,m7b,m7c,m7d,m7x,m7y;
118
unsigned char m7sel;
119
int m7write;
120
#endif
121
122
void initppu()
123
{
124
ppu_vram=(unsigned char *)malloc(65536);
125
ppu_vramw=(unsigned short *)ppu_vram;
126
memset(ppu_vram,0,65536);
127
memset(objram,0,1024);
128
memset(&sprites,0,sizeof(sprites));
129
maketables();
130
}
131
132
void resetppu()
133
{
134
memset(ppu_vram,0,65536);
135
memset(objram,0,1024);
136
memset(&sprites,0,sizeof(sprites));
137
}
138
139
void maketables()
140
{
141
int c;
142
for (c=0; c<16; c++)
143
{
144
ppu_bittable[0][c]=0;
145
if (c&0x8) ppu_bittable[0][c]|=0x00000001;
146
if (c&0x4) ppu_bittable[0][c]|=0x00000100;
147
if (c&0x2) ppu_bittable[0][c]|=0x00010000;
148
if (c&0x1) ppu_bittable[0][c]|=0x01000000;
149
ppu_bittable[1][c]=0;
150
if (c&0x1) ppu_bittable[1][c]|=0x00000001;
151
if (c&0x2) ppu_bittable[1][c]|=0x00000100;
152
if (c&0x4) ppu_bittable[1][c]|=0x00010000;
153
if (c&0x8) ppu_bittable[1][c]|=0x01000000;
154
ppu_masktable[0][c]=0;
155
if (c&0x8) ppu_masktable[0][c]|=0x000000FF;
156
if (c&0x4) ppu_masktable[0][c]|=0x0000FF00;
157
if (c&0x2) ppu_masktable[0][c]|=0x00FF0000;
158
if (c&0x1) ppu_masktable[0][c]|=0xFF000000;
159
ppu_masktable[1][c]=0;
160
if (c&0x1) ppu_masktable[1][c]|=0x000000FF;
161
if (c&0x2) ppu_masktable[1][c]|=0x0000FF00;
162
if (c&0x4) ppu_masktable[1][c]|=0x00FF0000;
163
if (c&0x8) ppu_masktable[1][c]|=0xFF000000;
164
}
165
for (c=0; c<256; c++)
166
{
167
fliptable[c]=0;
168
if (c&0x01) fliptable[c]|=0x80;
169
if (c&0x02) fliptable[c]|=0x40;
170
if (c&0x04) fliptable[c]|=0x20;
171
if (c&0x08) fliptable[c]|=0x10;
172
if (c&0x10) fliptable[c]|=0x08;
173
if (c&0x20) fliptable[c]|=0x04;
174
if (c&0x40) fliptable[c]|=0x02;
175
if (c&0x80) fliptable[c]|=0x01;
176
}
177
ppu_coltable[0]=0;
178
ppu_coltable[1]=0x01010101;
179
ppu_coltable[2]=0x02020202;
180
ppu_coltable[3]=0x03030303;
181
ppu_coltable[4]=0x04040404;
182
ppu_coltable[5]=0x05050505;
183
ppu_coltable[6]=0x06060606;
184
ppu_coltable[7]=0x07070707;
185
ppu_coltable16[0]=0;
186
ppu_coltable16[1]=0x00010001;
187
ppu_coltable16[2]=0x00020002;
188
ppu_coltable16[3]=0x00030003;
189
ppu_coltable16[4]=0x00040004;
190
ppu_coltable16[5]=0x00050005;
191
ppu_coltable16[6]=0x00060006;
192
ppu_coltable16[7]=0x00070007;
193
#ifdef MODE7
194
for (c=0; c<256; c++) hmostable[c]=c|(c<<8)|(c<<16)|(c<<24);
195
// for (c=0;c<8;c++) printf("col %08X\n",ppu_coltable[c]);
196
#endif
197
}
198
int ins;
199
void dumpppuregs()
200
{
201
printf("PPU regs :\n");
202
printf("BG : %04X %04X %04X %04X\n",ppu_bg[0],ppu_bg[1],ppu_bg[2],ppu_bg[3]);
203
printf("CHR : %04X %04X %04X %04X\n",ppu_chr[0],ppu_chr[1],ppu_chr[2],ppu_chr[3]);
204
}
205
206
void writeppu(unsigned short addr, unsigned char val)
207
{
208
uint32 tempw,tempw2;
209
// if (curline==32) printf("Writing to %04X %02X line 32\n",addr,val);
210
switch (addr)
211
{
212
case 0x2100: /*Screen Display Register*/
213
ppu_sdr=val;
214
return;
215
case 0x2101: /*Sprite Size Register*/
216
// printf("Name select %i\n",(val>>3)&3);
217
sprchraddr=(val&3)<<14;
218
objnamesel=((val>>3)&3)<<13;
219
val>>=5;
220
val<<=1;
221
objsize[0]=objsizes[val][0];
222
objsize[1]=objsizes[val][1];
223
objsize[2]=objsizes[val+1][0];
224
objsize[3]=objsizes[val+1][1];
225
return;
226
case 0x2102:
227
objaddr&=0x100;
228
objaddr|=val;
229
// printf("OBJ addr now %03X\n",objaddr<<1);
230
sobjaddr=objaddr;
231
return;
232
case 0x2103:
233
if (val&1)
234
objaddr|=0x100;
235
else
236
objaddr&=0xFE;
237
238
firstobjwrite=1;
239
sobjaddr=objaddr;
240
return;
241
case 0x2104:
242
243
if (objaddr>0x10F) {
244
objaddr=0;
245
firstobjwrite=1;
246
}
247
248
if (firstobjwrite)
249
objram[objaddr<<1]=val;
250
else
251
{
252
objram[(objaddr<<1)+1]=val;
253
objaddr++;
254
}
255
firstobjwrite^=1;
256
return;
257
case 0x2105: /*Screen Mode Register*/
258
ppu_mode=val;
259
return;
260
case 0x2106: /*Mosaic*/
261
mosaic=val;
262
return;
263
case 0x2107: /*BG1 Address*/
264
addr=ppu_bg[0];
265
ppu_bg[0]=(val&0xFC)<<9;
266
bgdat[0]=val&3;
267
xsize[0]=val&1;
268
ymode[0]=(val&2)>>1;
269
if (addr==ppu_bg[0]) return;
270
rescan[0]=1;
271
272
return;
273
case 0x2108: /*BG2 Address*/
274
275
addr=ppu_bg[1];
276
ppu_bg[1]=(val&0xFC)<<9;
277
bgdat[1]=val&3;
278
xsize[1]=val&1;
279
ymode[1]=(val&2)>>1;
280
if (addr==ppu_bg[1]) return;
281
rescan[1]=1;
282
return;
283
case 0x2109: /*BG3 Address*/
284
285
addr=ppu_bg[2];
286
ppu_bg[2]=(val&0xFC)<<9;
287
bgdat[2]=val&3;
288
xsize[2]=val&1;
289
ymode[2]=(val&2)>>1;
290
if (addr==ppu_bg[2]) return;
291
rescan[2]=1;
292
return;
293
case 0x210A: /*BG4 Address*/
294
addr=ppu_bg[3];
295
ppu_bg[3]=(val&0xFC)<<9;
296
bgdat[3]=val&3;
297
xsize[3]=val&1;
298
ymode[3]=(val&2)>>1;
299
if (addr==ppu_bg[3]) return;
300
rescan[3]=1;
301
302
return;
303
case 0x210B: /*BG1+2 CHR Address*/
304
ppu_chr[0]=(val&0xF)<<13;
305
ppu_chr[1]=(val>>4)<<13;
306
// printf("CHR 0 %04X 1 %04X %02X %04X\n",ppu_chr[0],ppu_chr[1],val,pc);
307
return;
308
case 0x210C: /*BG2+3 CHR Address*/
309
ppu_chr[2]=(val&0xF)<<13;
310
ppu_chr[3]=(val>>4)<<13;
311
return;
312
case 0x210D: /*BG1 Horizontal Scroll*/
313
ppu_xs[0] = (ppu_xs[0]>>8)|(val<<8);
314
return;
315
case 0x210E: /*BG1 Vertical Scroll*/
316
ppu_ys[0] = (ppu_ys[0]>>8)|(val<<8);
317
// printf("BG1 vscroll %04X %04X\n",ppu_ys[0],pc);
318
return;
319
case 0x210F: /*BG2 Horizontal Scroll*/
320
ppu_xs[1] = (ppu_xs[1]>>8)|(val<<8);
321
return;
322
case 0x2110: /*BG2 Vertical Scroll*/
323
ppu_ys[1] = (ppu_ys[1]>>8)|(val<<8);
324
return;
325
case 0x2111: /*BG3 Horizontal Scroll*/
326
ppu_xs[2] = (ppu_xs[2]>>8)|(val<<8);
327
return;
328
case 0x2112: /*BG3 Vertical Scroll*/
329
ppu_ys[2] = (ppu_ys[2]>>8)|(val<<8);
330
return;
331
case 0x2113: /*BG4 Horizontal Scroll*/
332
ppu_xs[3] = (ppu_xs[3]>>8)|(val<<8);
333
return;
334
case 0x2114: /*BG4 Vertical Scroll*/
335
ppu_ys[3] = (ppu_ys[3]>>8)|(val<<8);
336
return;
337
case 0x2115: /*Video Port Control*/
338
ppu_vidportc=val;
339
// printf("Vidportc %02X\n",val);
340
switch (ppu_vidportc&3)
341
{
342
case 0:
343
ppu_vinc=1;
344
break;
345
case 1:
346
ppu_vinc=32;
347
break;
348
case 2:
349
case 3:
350
ppu_vinc=128;
351
break;
352
}
353
switch (ppu_vidportc&0xC)
354
{
355
case 0:
356
ppu_fgcount=0;
357
break;
358
case 4:
359
ppu_fgcount=0x20;
360
ppu_fgmask=0xFF;
361
ppu_fgshift=5;
362
break;
363
case 8:
364
ppu_fgcount=0x40;
365
ppu_fgmask=0x1FF;
366
ppu_fgshift=6;
367
break;
368
case 12:
369
ppu_fgcount=0x80;
370
ppu_fgmask=0x3FF;
371
ppu_fgshift=7;
372
break;
373
}
374
return;
375
case 0x2116: /*Video Addr Low*/
376
ppu_firstread=1;
377
ppu_vaddr=(ppu_vaddr&0x7F00)|val;
378
return;
379
case 0x2117: /*Video Addr High*/
380
ppu_firstread=1;
381
ppu_vaddr=(ppu_vaddr&0xFF)|((val&0x7F)<<8);
382
// printf("Video addr %04X\n",ppu_vaddr<<1);
383
return;
384
case 0x2118: /*Video Data Low*/
385
ppu_firstread=1;
386
if (ppu_fgcount)
387
{
388
tempw=ppu_vaddr&ppu_fgmask;
389
tempw2=(ppu_vaddr&~ppu_fgmask)+(tempw>>ppu_fgshift)+((tempw&(ppu_fgcount-1))<<3);
390
ppu_vram[(tempw2&0x7FFF)<<1]=val;
391
tileupdate[(tempw2&0x7FFF)>>3]=1;
392
}
393
else
394
{
395
ppu_vram[(ppu_vaddr&0x7FFF)<<1]=val;
396
tileupdate[(ppu_vaddr&0x7FFF)>>3]=1;
397
}
398
if (!(ppu_vidportc&0x80)) ppu_vaddr+=ppu_vinc;
399
return;
400
case 0x2119: /*Video Data High*/
401
ppu_firstread=1;
402
if (ppu_fgcount)
403
{
404
tempw=ppu_vaddr&ppu_fgmask;
405
tempw2=(ppu_vaddr&~ppu_fgmask)+(tempw>>ppu_fgshift)+((tempw&(ppu_fgcount-1))<<3)+1;
406
ppu_vram[(tempw2&0x7FFF)<<1]=val;
407
tileupdate[(tempw2&0x7FFF)>>3]=1;
408
}
409
else
410
{
411
ppu_vram[((ppu_vaddr&0x7FFF)<<1)+1]=val;
412
tileupdate[(ppu_vaddr&0x7FFF)>>3]=1;
413
tempw2=ppu_vaddr;
414
}
415
if (((tempw2<<1)&0xF000)==ppu_bg[0]) rescan[0]=1;
416
if (((tempw2<<1)&0xF000)==ppu_bg[1]) rescan[1]=1;
417
if (((tempw2<<1)&0xF000)==ppu_bg[2]) rescan[2]=1;
418
if (((tempw2<<1)&0xF000)==ppu_bg[3]) rescan[3]=1;
419
if (ppu_vidportc&0x80) ppu_vaddr+=ppu_vinc;
420
// tileupdate[(ppu_vaddr&0x7FFF)>>3]=1;
421
// tileupdate4[(ppu_vaddr&0x7FFF)>>4]=1;
422
return;
423
#ifdef MODE7
424
case 0x211A:
425
m7sel=val;
426
// printf("M7 sel %02X\n",val);
427
return;
428
case 0x211B:
429
m7a=(m7a>>8)|(val<<8);
430
matrixr=(short)m7a*((short)m7b>>8);
431
// printf("M7A write %02X at line %i\n",val,curline);
432
return;
433
case 0x211C:
434
m7b=(m7b>>8)|(val<<8);
435
matrixr=(short)m7a*((short)m7b>>8);
436
// printf("M7B write %02X at line %i\n",val,curline);
437
m7write=1;
438
return;
439
case 0x211D:
440
m7c=(m7c>>8)|(val<<8);
441
// printf("M7C write %02X at line %i\n",val,curline);
442
return;
443
case 0x211E:
444
m7d=(m7d>>8)|(val<<8);
445
// printf("M7D write %02X at line %i\n",val,curline);
446
// m7write=1;
447
return;
448
case 0x211F:
449
m7x=(m7x>>8)|(val<<8);
450
return;
451
case 0x2120:
452
m7y=(m7y>>8)|(val<<8);
453
return;
454
#endif
455
case 0x2121: /*Colour Selection Register*/
456
ppu_cgramaddr=(val<<1)&0x1FF;
457
// printf("CGRAM addr %02X %04X %04X\n",val,ppu_cgramaddr,pc);
458
return;
459
case 0x2122: /*Colour Data Register*/
460
//printf("CGRAM %04X write %02X\n",ppu_cgramaddr,val);
461
if(ppu_cgramaddr&1){
462
tempw=ppu_cgram[ppu_cgramaddr>>1]|=val<<8;
463
ppu_palette[ppu_cgramaddr>>1]=RGB555toRGB24(tempw);
464
}
465
else
466
ppu_cgram[ppu_cgramaddr>>1]=val;
467
ppu_cgramaddr++;
468
return;
469
case 0x2123:
470
case 0x2124:
471
//printf("%x %x\n", addr, val);
472
return;
473
case 0x2125: /*Colour window settings*/
474
ppu_wobjsel=val;
475
//printf("2125 write %02X\n",val);
476
return;
477
case 0x2126: /*Window regs*/
478
ppu_w1l=val;
479
// printf("2126 write %02X\n",val);
480
return;
481
case 0x2127:
482
ppu_w1r=val;
483
// printf("2127 write %02X\n",val);
484
return;
485
case 0x2128:
486
ppu_w2l=val;
487
// printf("2128 write %02X\n",val);
488
return;
489
case 0x2129:
490
ppu_w2r=val;
491
// printf("2129 write %02X\n",val);
492
return;
493
case 0x212B: /*Mask logic for colour window*/
494
wobjlog=val;
495
// printf("WOBJLOG %02X\n",val);
496
return;
497
case 0x212C: /*Main Screen*/
498
ppu_main=val;
499
// printf("Main screen %02X %02X:%04X\n",val,pbr,pc);
500
return;
501
case 0x212D: /*Sub Screen*/
502
ppu_sub=val;
503
// printf("Sub screen %02X %02X:%04X\n",val,pbr,pc);
504
// printf("Sub screen %02X\n",val);
505
return;
506
case 0x2130: /*Fixed colour addition*/
507
ppu_cgwsel=val;
508
//printf("2130 write %02X line %i\n",val,curline);
509
return;
510
case 0x2131: /*Addition/Subtraction*/
511
ppu_cgadsub=val;
512
//printf("2131 write %02X line %i\n",val,curline);
513
return;
514
case 0x2132: /*Fixed colour data*/
515
if (val&0x20) ppufc=(ppufc&0xffe0)|(val&0x1F);
516
if (val&0x40) ppufc=(ppufc&0xfc1f)|((val&0x1F)<<5);
517
if (val&0x80) ppufc=(ppufc&0x83ff)|((val&0x1F)<<10);
518
ppu_fixedcol=RGB555toRGB24(ppufc);
519
//printf("2132 write %02X line %i %02X:%04X %x\n",val,curline,pbr,pc, ppufc);
520
return;
521
case 0x2140:
522
case 0x2141:
523
case 0x2142:
524
case 0x2143:
525
case 0x2144:
526
case 0x2145:
527
case 0x2146:
528
case 0x2147:
529
// if ((pc>0x9615)&&(pc<0x963F)) printf("Write %04X %02X\n",addr,val);
530
#ifdef SOUND
531
if (spcemu) write214x(addr&0x2143,val);
532
else
533
#endif
534
setzf=0;
535
return;
536
case 0x2180: /*VRAM write*/
537
// if ((ppu_wramaddr)==0) printf("0 write %02X at %02X:%04X\n",val,pbr,pc);
538
ram[ppu_wramaddr]=val;
539
ppu_wramaddr=(ppu_wramaddr+1)&0x1FFFF;
540
return;
541
case 0x2181: /*VRAM addr low*/
542
ppu_wramaddr=(ppu_wramaddr&0x1FF00)|val;
543
return;
544
case 0x2182: /*VRAM addr mid*/
545
ppu_wramaddr=(ppu_wramaddr&0x100FF)|(val<<8);
546
return;
547
case 0x2183: /*VRAM addr high*/
548
ppu_wramaddr=(ppu_wramaddr&0xFFFF)|((val&1)<<16);
549
return;
550
}
551
// printf("Bad PPU write %04X %02X\n",addr,val);
552
/* dumpregs();
553
exit(-1);*/
554
}
555
556
unsigned char *ram;
557
558
int skip=0;
559
560
unsigned char doskipper()
561
{
562
int temp=skip;
563
skip++;
564
if (skip==19) skip=0;
565
switch (temp>>1)
566
{
567
case 0:
568
case 1:
569
setzf=2;
570
return 0;
571
case 2:
572
if (temp&1) return reg_A.b.h;
573
else return reg_A.b.l;
574
break;
575
case 3:
576
if (temp&1) return reg_X.b.h;
577
else return reg_X.b.l;
578
break;
579
case 4:
580
if (temp&1) return reg_Y.b.h;
581
else return reg_Y.b.l;
582
break;
583
case 5:
584
if (temp&1) return 0xBB;
585
else return 0xAA;
586
break;
587
case 6:
588
setzf=2;
589
return 0;
590
case 7:
591
if (temp&1) return 0xBB;
592
else return 0xAA;
593
break;
594
case 8:
595
if (temp&1) return 0x33;
596
else return 0x33;
597
break;
598
case 9:
599
return 0;
600
}
601
printf("Shouldn't have got here\n");
602
exit(-1);
603
}
604
605
inline unsigned short getareg() {
606
return reg_A.w;
607
}
608
609
unsigned short vlatch;
610
611
unsigned char readppu(unsigned short a)
612
{
613
unsigned char temp;
614
if (a>0x21FF) return 0x21;
615
switch (a)
616
{
617
case 0x2134:
618
return matrixr;
619
case 0x2135:
620
return matrixr>>8;
621
case 0x2136:
622
return matrixr>>16;
623
case 0x2137: /*Latch*/
624
vlatch=curline;
625
// printf("VLATCH %i %02X %02X:%04X\n",vlatch,vlatch,pbr,pc);
626
return 0xFF;
627
case 0x2139: /*VRAM Read Low*/
628
if (ppu_firstread)
629
{
630
ppu_firstread=0;
631
return ppu_vram[(ppu_vaddr<<1)&0xFFFF];
632
}
633
temp=ppu_vram[((ppu_vaddr<<1)-2)&0xFFFF];
634
// printf("Read 2139 vinc %i %i\n",ppu_vinc,ppu_vidportc&3);
635
if (!(ppu_vidportc&0x80))
636
ppu_vaddr+=ppu_vinc;
637
return temp;
638
case 0x213A: /*VRAM Read High*/
639
if (ppu_firstread)
640
{
641
ppu_firstread=0;
642
return ppu_vram[((ppu_vaddr<<1)+1)&0xFFFF];
643
}
644
temp=ppu_vram[((ppu_vaddr<<1)-1)&0xFFFF];
645
// printf("Read 213A vinc %i %i\n",ppu_vinc,ppu_vidportc&3);
646
if (ppu_vidportc&0x80)
647
ppu_vaddr+=ppu_vinc;
648
return temp;
649
650
case 0x213D: /*Vertical counter*/
651
temp=vlatch&0xFF;
652
vlatch>>=8;
653
return temp;
654
case 0x213E: /*PPU time/range flags*/
655
// printf("Read 213E %02X:%04X\n",pbr,pc);
656
return 0;
657
//S=1FEE
658
case 0x213F:
659
if (palf) return 0x10;
660
return 0x00; /*NTSC*/ ///*PAL*/
661
662
case 0x2140:
663
case 0x2141:
664
case 0x2142:
665
case 0x2143: /*SPC*/
666
case 0x2144:
667
case 0x2145:
668
case 0x2146:
669
case 0x2147:
670
#ifdef SOUND
671
if (spcemu) return read214x(a&0x2143);
672
#endif
673
674
temp=doskipper();
675
// printf("%02X %02X:%04X %04X\n",temp,pbr,pc,a);
676
return temp;
677
678
case 0x2180: /*WRAM read*/
679
temp=ram[ppu_wramaddr];
680
ppu_wramaddr=(ppu_wramaddr+1)&0x1FFFF;
681
return temp;
682
case 0x2181: /*WRAM addr low*/
683
return ppu_wramaddr;
684
case 0x2182: /*WRAM addr mid*/
685
return ppu_wramaddr>>8;
686
case 0x2183: /*WRAM addr high*/
687
return ppu_wramaddr>>16;
688
689
default:
690
// return 0;
691
// printf("Bad PPU read %04X %02X:%04X %i\n",a,pbr,pc,stage);
692
return 0;
693
// dumpregs();
694
// exit(-1);
695
}
696
}
697
698
void vblankhdma()
699
{
700
int c;
701
for (c=0; c<8; c++)
702
{
703
hdma.hdmaon[c]=1;
704
hdma.hdmacount[c]=0;
705
hdma.srcbank[c]=dma.srcbank[c];
706
hdma.src[c]=dma.src[c];
707
}
708
}
709
710
static inline unsigned char readf(unsigned char b, unsigned short a)
711
{
712
if (mempointv[b][a>>13])
713
return mempoint[b][a>>13][a&0x1FFF];
714
else
715
return 0;
716
}
717
718
void doline(int line)
719
{
720
int c;
721
unsigned char mask=1;
722
// printf("HDMA on\n");
723
for (c=0; c<8; c++, mask<<=1)
724
{
725
if (hdmaena&mask && hdma.hdmaon[c])
726
{
727
if (!hdma.hdmacount[c])
728
{
729
stage=162;
730
hdma.hdmacount[c]=readf(hdma.srcbank[c],hdma.src[c]);
731
hdma.src[c]++;
732
if (!hdma.hdmacount[c])
733
{
734
hdma.hdmaon[c]=0;
735
continue;
736
}
737
if (hdma.hdmacount[c]&0x80)
738
{
739
hdma.hdmacount[c]&=0x7F;
740
hdma.repeat[c]=1;
741
}
742
else
743
hdma.repeat[c]=0;
744
// if (dma.dest[c]==0xD) printf("210D write line %03i src %02X:%04X ctrl %02X count %i\n",line,hdma.srcbank[c],hdma.src[c],dma.ctrl[c],hdma.hdmacount[c]);
745
if (dma.ctrl[c]&0x40)
746
{
747
hdma.ta[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8);
748
hdma.src[c]+=2;
749
switch (dma.ctrl[c]&7)
750
{
751
case 0: /*One reg write once*/
752
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c]);
753
hdma.ta[c]++;
754
break;
755
case 1: /*Two regs write once*/
756
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8);
757
hdma.ta[c]+=2;
758
break;
759
case 2: /*One reg write twice*/
760
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8);
761
hdma.ta[c]+=2;
762
break;
763
case 3: /*Two regs write twice*/
764
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8)|(readf(hdma.ibank[c],hdma.ta[c]+2)<<16)|(readf(hdma.ibank[c],hdma.ta[c]+3)<<24);
765
hdma.ta[c]+=4;
766
break;
767
case 4: /*Four regs write once*/
768
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8)|(readf(hdma.ibank[c],hdma.ta[c]+2)<<16)|(readf(hdma.ibank[c],hdma.ta[c]+3)<<24);
769
hdma.ta[c]+=4;
770
break;
771
772
default:
773
printf("Bad HDMA indirect mode %i count %i dest %02X data %02X:%04X\n",dma.ctrl[c]&7,hdma.hdmacount[c],dma.dest[c],hdma.ibank[c],hdma.ta[c]);
774
dumpregs();
775
exit(-1);
776
}
777
}
778
else
779
{
780
switch (dma.ctrl[c]&7)
781
{
782
case 0: /*One reg write once*/
783
stage=160;
784
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c]);
785
hdma.src[c]++;
786
stage=161;
787
break;
788
case 1: /*Two regs write once*/
789
stage=160;
790
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8);
791
hdma.src[c]+=2;
792
stage=161;
793
break;
794
case 2: /*One reg write twice*/
795
stage=160;
796
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8);
797
hdma.src[c]+=2;
798
stage=161;
799
break;
800
case 3: /*Two regs write twice*/
801
stage=160;
802
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8)|(readf(hdma.srcbank[c],hdma.src[c]+2)<<16)|(readf(hdma.srcbank[c],hdma.src[c]+3)<<24);
803
hdma.src[c]+=4;
804
stage=161;
805
break;
806
case 4: /*Four regs*/
807
stage=160;
808
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8)|(readf(hdma.srcbank[c],hdma.src[c]+2)<<16)|(readf(hdma.srcbank[c],hdma.src[c]+3)<<24);
809
hdma.src[c]+=4;
810
stage=161;
811
break;
812
813
default:
814
printf("Bad HDMA mode %i count %i dest %02X\n",dma.ctrl[c]&7,hdma.hdmacount[c],dma.dest[c]);
815
dumpregs();
816
exit(-1);
817
}
818
}
819
switch (dma.ctrl[c]&7)
820
{
821
case 0: /*One reg write once*/
822
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
823
break;
824
case 1: /*Two regs write once*/
825
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
826
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>8);
827
break;
828
case 2: /*One reg write twice*/
829
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
830
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]>>8);
831
break;
832
case 3: /*Two regs write twice*/
833
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
834
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]>>8);
835
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>16);
836
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>24);
837
break;
838
case 4: /*Four regs*/
839
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
840
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>8);
841
writeppu(0x2100|dma.dest[c]+2,hdma.hdmaval[c]>>16);
842
writeppu(0x2100|dma.dest[c]+3,hdma.hdmaval[c]>>24);
843
break;
844
}
845
}
846
else
847
{
848
hdma.hdmacount[c]--;
849
if (hdma.repeat[c])
850
{
851
if (dma.ctrl[c]&0x40)
852
{
853
switch (dma.ctrl[c]&7)
854
{
855
case 0: /*One reg write once*/
856
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c]);
857
hdma.ta[c]++;
858
break;
859
case 1: /*Two regs write once*/
860
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8);
861
hdma.ta[c]+=2;
862
break;
863
case 2: /*One reg write twice*/
864
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8);
865
hdma.ta[c]+=2;
866
break;
867
case 3: /*Two regs write twice*/
868
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8)|(readf(hdma.ibank[c],hdma.ta[c]+2)<<16)|(readf(hdma.ibank[c],hdma.ta[c]+3)<<24);
869
hdma.ta[c]+=4;
870
break;
871
case 4: /*Four regs write once*/
872
hdma.hdmaval[c]=readf(hdma.ibank[c],hdma.ta[c])|(readf(hdma.ibank[c],hdma.ta[c]+1)<<8)|(readf(hdma.ibank[c],hdma.ta[c]+2)<<16)|(readf(hdma.ibank[c],hdma.ta[c]+3)<<24);
873
hdma.ta[c]+=4;
874
break;
875
876
default:
877
printf("Bad HDMA indirect mode %i count %i dest %02X data %02X:%04X\n",dma.ctrl[c]&7,hdma.hdmacount[c],dma.dest[c],hdma.ibank[c],hdma.ta[c]);
878
dumpregs();
879
exit(-1);
880
}
881
}
882
else
883
{
884
switch (dma.ctrl[c]&7)
885
{
886
case 0: /*One reg write once*/
887
stage=160;
888
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c]);
889
hdma.src[c]++;
890
stage=161;
891
break;
892
case 1: /*Two regs write once*/
893
stage=160;
894
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8);
895
hdma.src[c]+=2;
896
stage=161;
897
break;
898
case 2: /*One reg write twice*/
899
stage=160;
900
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8);
901
hdma.src[c]+=2;
902
stage=161;
903
break;
904
case 3: /*Two regs write twice*/
905
stage=160;
906
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8)|(readf(hdma.srcbank[c],hdma.src[c]+2)<<16)|(readf(hdma.srcbank[c],hdma.src[c]+3)<<24);
907
hdma.src[c]+=4;
908
stage=161;
909
break;
910
case 4: /*Four regs*/
911
stage=160;
912
hdma.hdmaval[c]=readf(hdma.srcbank[c],hdma.src[c])|(readf(hdma.srcbank[c],hdma.src[c]+1)<<8)|(readf(hdma.srcbank[c],hdma.src[c]+2)<<16)|(readf(hdma.srcbank[c],hdma.src[c]+3)<<24);
913
hdma.src[c]+=4;
914
stage=161;
915
break;
916
917
default:
918
printf("Bad HDMA mode %i count %i dest %02X\n",dma.ctrl[c]&7,hdma.hdmacount[c],dma.dest[c]);
919
dumpregs();
920
exit(-1);
921
}
922
}
923
switch (dma.ctrl[c]&7)
924
{
925
case 0: /*One reg write once*/
926
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
927
break;
928
case 1: /*Two regs write once*/
929
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
930
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>8);
931
break;
932
case 2: /*One reg write twice*/
933
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
934
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]>>8);
935
break;
936
case 3: /*Two regs write twice*/
937
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
938
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]>>8);
939
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>16);
940
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>24);
941
break;
942
case 4: /*Four regs*/
943
writeppu(0x2100|dma.dest[c],hdma.hdmaval[c]);
944
writeppu(0x2100|dma.dest[c]+1,hdma.hdmaval[c]>>8);
945
writeppu(0x2100|dma.dest[c]+2,hdma.hdmaval[c]>>16);
946
writeppu(0x2100|dma.dest[c]+3,hdma.hdmaval[c]>>24);
947
break;
948
}
949
}
950
}
951
}
952
}
953
// printf("HDMA off\n");
954
lines_bg[line][0]=ppu_bg[0]>>1;
955
lines_chr[line][0]=ppu_chr[0]>>1;
956
lines_bg[line][1]=ppu_bg[1]>>1;
957
lines_chr[line][1]=ppu_chr[1]>>1;
958
lines_bg[line][2]=ppu_bg[2]>>1;
959
lines_chr[line][2]=ppu_chr[2]>>1;
960
lines_bg[line][3]=ppu_bg[3]>>1;
961
lines_chr[line][3]=ppu_chr[3]>>1;
962
lines_mode[line]=ppu_mode&7;
963
lines[line].tsize[3]=(ppu_mode&0x80)>>7;
964
lines[line].tsize[2]=(ppu_mode&0x40)>>6;
965
lines[line].tsize[1]=(ppu_mode&0x20)>>5;
966
lines[line].tsize[0]=(ppu_mode&0x10)>>4;
967
lines[line].screenon=!(ppu_sdr&0x80);
968
if (sblankchk) lines[line].screenon=1;
969
lines[line].mainena=ppu_main;
970
lines[line].subena=ppu_sub;
971
lines[line].bg3pri=(ppu_mode&8)>>3;
972
lines[line].xs[0]=ppu_xs[0];
973
lines[line].xs[1]=ppu_xs[1];
974
lines[line].xs[2]=ppu_xs[2];
975
lines[line].xs[3]=ppu_xs[3];
976
lines[line].ys[0]=ppu_ys[0];
977
lines[line].ys[1]=ppu_ys[1];
978
lines[line].ys[2]=ppu_ys[2];
979
lines[line].ys[3]=ppu_ys[3];
980
lines[line].xsize[0]=xsize[0]&1;
981
lines[line].ysize[0]=ymode[0]&1;
982
lines[line].xsize[1]=bgdat[1]&1;
983
lines[line].ysize[1]=(bgdat[1]&2)>>1;
984
lines[line].xsize[2]=bgdat[2]&1;
985
lines[line].ysize[2]=(bgdat[2]&2)>>1;
986
lines[line].xsize[3]=bgdat[3]&1;
987
lines[line].ysize[3]=(bgdat[3]&2)>>1;
988
989
lines[line].w1l=ppu_w1l;
990
lines[line].w1r=ppu_w1r;
991
lines[line].w2l=ppu_w2l;
992
lines[line].w2r=ppu_w2r;
993
#ifdef MODE7
994
lines[line].fixedcol=ppufc;
995
lines[line].bright=ppu_sdr&0xF;
996
if (ppu_sdr&0x80) lines[line].bright=0;
997
lines[line].m7a=m7a;
998
lines[line].m7c=m7c;
999
lines[line].m7x=m7x;
1000
lines[line].m7y=m7y;
1001
lines[line].m7sel=m7sel;
1002
lines[line].m7b=m7b;
1003
lines[line].m7d=m7d;
1004
lines[line].mosaic=mosaic>>4;
1005
lines[line].mena=mosaic&0xF;
1006
if (m7write || !line)
1007
lines[line].m7change=1;
1008
else
1009
lines[line].m7change=0;
1010
m7write=0;
1011
lines[line].cgwsel=ppu_cgwsel;
1012
lines[line].cgadsub=ppu_cgadsub;
1013
lines[line].wobjsel=ppu_wobjsel;
1014
if (line)
1015
{
1016
if ((ppu_w1l!=lines[line-1].w1l) ||
1017
(ppu_w1r!=lines[line-1].w1r) ||
1018
(ppu_w2l!=lines[line-1].w2l) ||
1019
(ppu_w2r!=lines[line-1].w2r))
1020
lines[line].wchg=1;
1021
else
1022
lines[line].wchg=0;
1023
}
1024
#endif
1025
}
1026
1027
unsigned short ylookup[2][64]=
1028
{
1029
{ 0x000,0x020,0x040,0x060,0x080,0x0A0,0x0C0,0x0E0,
1030
0x100,0x120,0x140,0x160,0x180,0x1A0,0x1C0,0x1E0,
1031
0x200,0x220,0x240,0x260,0x280,0x2A0,0x2C0,0x2E0,
1032
0x300,0x320,0x340,0x360,0x380,0x3A0,0x3C0,0x3E0,
1033
0x000,0x020,0x040,0x060,0x080,0x0A0,0x0C0,0x0E0,
1034
0x100,0x120,0x140,0x160,0x180,0x1A0,0x1C0,0x1E0,
1035
0x200,0x220,0x240,0x260,0x280,0x2A0,0x2C0,0x2E0,
1036
0x300,0x320,0x340,0x360,0x380,0x3A0,0x3C0,0x3E0
1037
},
1038
{ 0x000,0x020,0x040,0x060,0x080,0x0A0,0x0C0,0x0E0,
1039
0x100,0x120,0x140,0x160,0x180,0x1A0,0x1C0,0x1E0,
1040
0x200,0x220,0x240,0x260,0x280,0x2A0,0x2C0,0x2E0,
1041
0x300,0x320,0x340,0x360,0x380,0x3A0,0x3C0,0x3E0,
1042
0x800,0x820,0x840,0x860,0x880,0x8A0,0x8C0,0x8E0,
1043
0x900,0x920,0x940,0x960,0x980,0x9A0,0x9C0,0x9E0,
1044
0xA00,0xA20,0xA40,0xA60,0xA80,0xAA0,0xAC0,0xAE0,
1045
0xB00,0xB20,0xB40,0xB60,0xB80,0xBA0,0xBC0,0xBE0
1046
}
1047
};
1048
1049
unsigned short xlookup[2][64]=
1050
{
1051
{ 0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,
1052
0x008,0x009,0x00A,0x00B,0x00C,0x00D,0x00E,0x00F,
1053
0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,
1054
0x018,0x019,0x01A,0x01B,0x01C,0x01D,0x01E,0x01F,
1055
0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,
1056
0x008,0x009,0x00A,0x00B,0x00C,0x00D,0x00E,0x00F,
1057
0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,
1058
0x018,0x019,0x01A,0x01B,0x01C,0x01D,0x01E,0x01F
1059
},
1060
{ 0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,
1061
0x008,0x009,0x00A,0x00B,0x00C,0x00D,0x00E,0x00F,
1062
0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,
1063
0x018,0x019,0x01A,0x01B,0x01C,0x01D,0x01E,0x01F,
1064
0x400,0x401,0x402,0x403,0x404,0x405,0x406,0x407,
1065
0x408,0x409,0x40A,0x40B,0x40C,0x40D,0x40E,0x40F,
1066
0x410,0x411,0x412,0x413,0x414,0x415,0x416,0x417,
1067
0x418,0x419,0x41A,0x41B,0x41C,0x41D,0x41E,0x41F
1068
},
1069
};
1070
1071
void decodesprites()
1072
{
1073
int c;
1074
int sprsize;
1075
int addrtemp=543;
1076
int tempval,temppos=0;
1077
tempval=objram[addrtemp];
1078
for (c=127; c>=0; c--)
1079
{
1080
sprites.x[c]=objram[c<<2];
1081
if (tempval&0x40) sprites.x[c]|=256;
1082
sprites.y[c]=objram[(c<<2)+1];
1083
sprites.t[c]=objram[(c<<2)+2]|((objram[(c<<2)+3]&1)<<8);
1084
sprites.c[c]=(ppu_coltable[(objram[(c<<2)+3]>>1)&7]|0x08080808)<<4;
1085
if ((objram[(c<<2)+3]>>1)&4) sprites.c[c]|=0x80008000;
1086
// else sprites.c[c]=(ppu_coltable[(objram[(c<<2)+3]>>1)&7]|0x08080808)<<4;
1087
sprites.p[c]=(objram[(c<<2)+3]>>4)&3;
1088
sprites.hf[c]=(objram[(c<<2)+3]&0x40)>>4;
1089
sprites.vf[c]=(8-((objram[(c<<2)+3]&0x80)>>7))&7;
1090
sprsize=tempval&0x80;
1091
if (sprsize)
1092
{
1093
sprites.sx[c]=objsize[2];
1094
sprites.sy[c]=objsize[3];
1095
}
1096
else
1097
{
1098
sprites.sx[c]=objsize[0];
1099
sprites.sy[c]=objsize[1];
1100
}
1101
tempval<<=2;
1102
temppos++;
1103
if (temppos==4)
1104
{
1105
addrtemp--;
1106
tempval=objram[addrtemp];
1107
}
1108
temppos&=3;
1109
}
1110
}
1111
1112
void dosprites(const int pri, const int ms)
1113
{
1114
int c,x,y,yy;
1115
int hstart,hend,hdir;
1116
int vstart,vend,vdir;
1117
unsigned short temptile;
1118
uint32 *tilep;
1119
uint32 *p, *p2;
1120
uint32 t1,t2;
1121
if (ms) c=lines[0].subena;
1122
else c=lines[0].mainena;
1123
if (!(c&0x10)) return;
1124
for (c=127; c>=0; c--)
1125
{
1126
if (pri==sprites.p[c])
1127
{
1128
sprites.x[c]&=511;
1129
sprites.y[c]&=511;
1130
if (sprites.x[c]&256) sprites.x[c]-=512;
1131
if (sprites.y[c]>240) sprites.y[c]-=256;
1132
if ((sprites.x[c]<264) && (sprites.y[c]<240) && ((sprites.x[c]+(sprites.sx[c]<<3))>=0) && ((sprites.y[c]+(sprites.sy[c]<<3))>=-16)) /*Clip offscreen sprites*/
1133
{
1134
if (sprites.vf[c])
1135
{
1136
vend=-8;
1137
vstart=(sprites.sy[c]-1)<<3;
1138
vdir=-8;
1139
temptile=(sprites.t[c]+(sprchraddr>>5))<<1;
1140
}
1141
else
1142
{
1143
vstart=0;
1144
vend=sprites.sy[c]<<3;
1145
vdir=8;
1146
temptile=(sprites.t[c]+(sprchraddr>>5))<<1;
1147
}
1148
if (sprites.t[c]&256) temptile+=(objnamesel>>5)<<1;
1149
if (sprites.hf[c])
1150
{
1151
hend=-8;
1152
hstart=(sprites.sx[c]-1)<<3;
1153
hdir=-8;
1154
}
1155
else
1156
{
1157
hstart=0;
1158
hend=sprites.sx[c]<<3;
1159
hdir=8;
1160
}
1161
for (y=vstart; y!=vend; y+=vdir)
1162
{
1163
if ((y+sprites.y[c]+16)>=0 && (y+sprites.y[c]+24)<=247)
1164
{
1165
for (x=hstart; x!=hend; x+=hdir)
1166
{
1167
if ((x+sprites.x[c]+16)>=0 && (x+sprites.x[c]+24)<=279)
1168
{
1169
for (yy=0; yy<8; yy++)
1170
{
1171
1172
p=(uint32 *)native_bitmap_pointer(x+sprites.x[c], y+yy+sprites.y[c]+1);
1173
tilep=tiless[temptile][sprites.hf[c]>>2][yy^sprites.vf[c]];
1174
t1=tilep[0]|tilep[32];
1175
t2=tilep[0]|(tilep[32]<<2)|sprites.c[c];
1176
p2=p+sprites.hf[c];
1177
for(; t1; p2++, t1>>=8, t2>>=8) if (t1&0xff) *p2=ppu_palette[t2&0xff];
1178
t1=tilep[1]|tilep[33];
1179
t2=tilep[1]|(tilep[33]<<2)|sprites.c[c];
1180
p2=p+4-sprites.hf[c];
1181
for(; t1; p2++, t1>>=8, t2>>=8) if(t1&0xff) *p2=ppu_palette[t2&0xff];
1182
1183
}
1184
}
1185
temptile+=2;
1186
}
1187
}
1188
else
1189
temptile+=(sprites.sx[c]<<1);
1190
if (vdir>0) temptile+=0x20;
1191
else temptile+=0x20;
1192
temptile-=(sprites.sx[c]<<1);
1193
}
1194
}
1195
}
1196
}
1197
}
1198
1199
1200
int bgs[4][8]=
1201
{
1202
{2,4,4,8,8,4,4,7},
1203
{2,4,4,4,2,2,0,7},
1204
{2,2,0,0,0,0,0,0},
1205
{2,0,0,0,0,0,0,0}
1206
};
1207
1208
#define getm7pixel(x2,y2) temp=ppu_vram[(((y2&~7)<<5)|((x2&~7)>>2))&0xFFFF]; col=ppu_vram[((temp<<7)+((y2&7)<<4)+((x2&7)<<1)+1)&0xFFFF]
1209
1210
/*Inaccuratly named - this actually draws an entire BG*/
1211
void drawbackground(const int bg, const int pri, const int bg3p, const int ms)
1212
{
1213
int line,bgbpp;
1214
int y,xx, y0;
1215
unsigned short tile,temptile;
1216
uint32 *p, *p2;
1217
unsigned short baddr;
1218
int x=0;
1219
uint32 col=0;
1220
int lin;
1221
int hflip;
1222
int tilemode;
1223
int yhalf;
1224
uint32 *tilep;
1225
unsigned short *xlk;
1226
uint32 t1,t2;
1227
static int showerr=-1;
1228
1229
for (line=0; line<224; line++)
1230
{
1231
bgbpp=bgs[bg][lines_mode[line]];
1232
if (bgbpp==7 && bg==0 && pri) continue;
1233
if (!lines[line].screenon) continue;
1234
if (!((ms ? lines[line].subena : lines[line].mainena)&(1<<bg))) continue;
1235
if (bg==2 && pri && lines_mode[line]==1 && (bg3p != lines[line].bg3pri)) continue;
1236
tilemode=lines[line].tsize[bg];
1237
baddr=lines_bg[line][bg];
1238
if(tilemode) {
1239
lin=(line+lines[line].ys[bg])&1023;
1240
p=(uint32 *)native_bitmap_pointer(-(lines[line].xs[bg]&15), line);
1241
baddr+=ylookup[lines[line].ysize[bg]][(lin>>4)&63];
1242
x=(lines[line].xs[bg]>>4)&63;
1243
}
1244
else {
1245
lin=(line+lines[line].ys[bg])&511;
1246
p=(uint32 *)native_bitmap_pointer(-(lines[line].xs[bg]&7), line);
1247
baddr+=ylookup[lines[line].ysize[bg]][(lin>>3)&63];
1248
x=(lines[line].xs[bg]>>3)&63;
1249
}
1250
y=lin&7;
1251
yhalf = (tilemode && (lin&8)) ? 1 : 0;
1252
xlk=xlookup[lines[line].xsize[bg]];
1253
1254
switch (bgbpp|tilemode)
1255
{
1256
case 2:
1257
for (xx=0; xx<264; xx+=8, x++)
1258
{
1259
tile=ppu_vramw[baddr+xlk[x&63]];
1260
if ((tile&0x2000)==pri)
1261
{
1262
temptile=(tile&1023)+(lines_chr[line][bg]>>3);
1263
y0=y^((8-(tile>>15))&7);
1264
if (!lines_mask[line] || tiledatm[temptile][y0])
1265
{
1266
col=ppu_coltable[(tile>>10)&7]<<2;
1267
hflip=(tile&0x4000)>>12;
1268
tilep=tiless[temptile][hflip>>2][y0];
1269
t1=tilep[0]|col;
1270
t2=tilep[0];
1271
p2=p+xx+hflip;
1272
for(; t2; p2++, t1>>=8, t2>>=8)
1273
if(t2&0xff)
1274
*p2=ppu_palette[t1&0xff];
1275
t1=tilep[1]|col;
1276
t2=tilep[1];
1277
p2=p+xx+4-hflip;
1278
for(; t2; p2++, t1>>=8, t2>>=8)
1279
if(t2&0xff)
1280
*p2=ppu_palette[t1&0xff];
1281
}
1282
}
1283
}
1284
break;
1285
case 4:
1286
for (xx=0; xx<264; xx+=8, x++)
1287
{
1288
tile=ppu_vramw[baddr+xlk[x&63]];
1289
if ((tile&0x2000)==pri)
1290
{
1291
temptile=((tile&1023)+(lines_chr[line][bg]>>4))<<1;
1292
y0=y^((8-(tile>>15))&7);
1293
if (!lines_mask[line] || (tiledatm[temptile][y0]|tiledatm[temptile+1][y0]))
1294
{
1295
col=ppu_coltable[(tile>>10)&7]<<4;
1296
hflip=(tile&0x4000)>>12;
1297
tilep=tiless[temptile][hflip>>2][y0];
1298
t1=tilep[0]|(tilep[32]<<2)|col;
1299
t2=tilep[0]|tilep[32];
1300
p2=p+xx+hflip;
1301
for(; t2; p2++, t1>>=8, t2>>=8)
1302
if(t2&0xff)
1303
*p2=ppu_palette[t1&0xff];
1304
t1=tilep[1]|(tilep[33]<<2)|col;
1305
t2=tilep[1]|tilep[33];
1306
p2=p+xx+4-hflip;
1307
for(; t2; p2++, t1>>=8, t2>>=8)
1308
if(t2&0xff)
1309
*p2=ppu_palette[t1&0xff];
1310
}
1311
}
1312
}
1313
break;
1314
1315
default:
1316
if(showerr!=ppu_mode)
1317
printf("unsupported mode %d %d %d\n", ppu_mode, bgbpp, tilemode);
1318
showerr=ppu_mode;
1319
}
1320
1321
lines_mask[line]=1;
1322
1323
}
1324
}
1325
1326
void renderscreen()
1327
{
1328
unsigned int line,c,d,s;
1329
uint32 baddr,tempw;
1330
for (c=0; c<4; c++)
1331
{
1332
if (rescan[c])
1333
{
1334
rescan[c]=0;
1335
switch (bgdat[c])
1336
{
1337
case 0:
1338
s=1024;
1339
break;
1340
case 1:
1341
case 2:
1342
s=2048;
1343
break;
1344
case 3:
1345
s=4096;
1346
break;
1347
}
1348
baddr=ppu_bg[c]>>1;
1349
prioritybuffer[c][0]=prioritybuffer[c][1]=0;
1350
for (d=0; d<s; d++)
1351
{
1352
if (ppu_vramw[baddr]&0x2000) prioritybuffer[c][1]=1;
1353
else prioritybuffer[c][0]=1;
1354
if (prioritybuffer[c][0] && prioritybuffer[c][1]) d=s;
1355
baddr++;
1356
}
1357
}
1358
}
1359
// printf("VBL\n");
1360
// decodesprites();
1361
updatetiles();
1362
if( (ppu_cgadsub&0x20) && ((ppu_cgwsel&0x30) !=0x30) ){
1363
1364
tempw=ppu_fixedcol;
1365
}
1366
else
1367
tempw=0;
1368
for (line=0; line<224; line++)
1369
{
1370
if (lines_mode[line]==7) lines_mask[line]=1;
1371
else lines_mask[line]=0;
1372
native_bitmap_clear_line(line, tempw);
1373
1374
}
1375
#define PRI 0x2000
1376
if (prioritybuffer[3][0]) drawbackground(3,0,0,1);
1377
if (prioritybuffer[2][0]) drawbackground(2,0,0,1);
1378
dosprites(0,1);
1379
UPDATE_SOUND;
1380
if (prioritybuffer[3][1]) drawbackground(3,PRI,0,1);
1381
if (prioritybuffer[2][1]) drawbackground(2,PRI,0,1);
1382
dosprites(1,1);
1383
UPDATE_SOUND;
1384
if (prioritybuffer[1][0]) drawbackground(1,0,0,1);
1385
if (prioritybuffer[0][0]) drawbackground(0,0,0,1);
1386
dosprites(2,1);
1387
UPDATE_SOUND;
1388
if (prioritybuffer[1][1]) drawbackground(1,PRI,0,1);
1389
if (prioritybuffer[0][1]) drawbackground(0,PRI,0,1);
1390
dosprites(3,1);
1391
UPDATE_SOUND;
1392
for (line=0; line<224; line++) lines_mask[line]=1;
1393
drawbackground(2,PRI,1,1);
1394
if (prioritybuffer[3][0]) drawbackground(3,0,0,0);
1395
if (prioritybuffer[2][0]) drawbackground(2,0,0,0);
1396
dosprites(0,0);
1397
UPDATE_SOUND;
1398
if (prioritybuffer[3][1]) drawbackground(3,PRI,0,0);
1399
if (prioritybuffer[2][1]) drawbackground(2,PRI,0,0);
1400
dosprites(1,0);
1401
UPDATE_SOUND;
1402
if (prioritybuffer[1][0]) drawbackground(1,0,0,0);
1403
if (prioritybuffer[0][0]) drawbackground(0,0,0,0);
1404
dosprites(2,0);
1405
UPDATE_SOUND;
1406
if (prioritybuffer[1][1]) drawbackground(1,PRI,0,0);
1407
if (prioritybuffer[0][1]) drawbackground(0,PRI,0,0);
1408
dosprites(3,0);
1409
UPDATE_SOUND;
1410
for (line=0; line<224; line++) lines_mask[line]=1;
1411
drawbackground(2,PRI,1,0);
1412
//window 1 clip hack
1413
if( ppu_w1l>0 && (ppu_wobjsel&0x33)==0x23) {
1414
for (line=0; line<224; line++)
1415
{
1416
uint32 *p=native_bitmap_pointer(0,line);
1417
int x;
1418
for(x=0; x<lines[line].w1l; x++) p[x]=0;
1419
for(x=lines[line].w1r; x<256; x++) p[x]=0;
1420
}
1421
}
1422
native_bitmap_to_screen();
1423
UPDATE_SOUND;
1424
1425
}
1426
1427