10 uchar pic[256*240*4*9];
13 pixel(int x, int y, int val, int back)
16 union { u8int c[4]; u32int l; } u;
18 static u8int palred[64] = {
19 0x7C, 0x00, 0x00, 0x44, 0x94, 0xA8, 0xA8, 0x88,
20 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21 0xBC, 0x00, 0x00, 0x68, 0xD8, 0xE4, 0xF8, 0xE4,
22 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 0xF8, 0x3C, 0x68, 0x98, 0xF8, 0xF8, 0xF8, 0xFC,
24 0xF8, 0xB8, 0x58, 0x58, 0x00, 0x78, 0x00, 0x00,
25 0xFC, 0xA4, 0xB8, 0xD8, 0xF8, 0xF8, 0xF0, 0xFC,
26 0xF8, 0xD8, 0xB8, 0xB8, 0x00, 0xF8, 0x00, 0x00,
28 static u8int palgreen[64] = {
29 0x7C, 0x00, 0x00, 0x28, 0x00, 0x00, 0x10, 0x14,
30 0x30, 0x78, 0x68, 0x58, 0x40, 0x00, 0x00, 0x00,
31 0xBC, 0x78, 0x58, 0x44, 0x00, 0x00, 0x38, 0x5C,
32 0x7C, 0xB8, 0xA8, 0xA8, 0x88, 0x00, 0x00, 0x00,
33 0xF8, 0xBC, 0x88, 0x78, 0x78, 0x58, 0x78, 0xA0,
34 0xB8, 0xF8, 0xD8, 0xF8, 0xE8, 0x78, 0x00, 0x00,
35 0xFC, 0xE4, 0xB8, 0xB8, 0xB8, 0xA4, 0xD0, 0xE0,
36 0xD8, 0xF8, 0xF8, 0xF8, 0xFC, 0xD8, 0x00, 0x00,
38 static u8int palblue[64] = {
39 0x7C, 0xFC, 0xBC, 0xBC, 0x84, 0x20, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
41 0xBC, 0xF8, 0xF8, 0xFC, 0xCC, 0x58, 0x00, 0x10,
42 0x00, 0x00, 0x00, 0x44, 0x88, 0x00, 0x00, 0x00,
43 0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0x98, 0x58, 0x44,
44 0x00, 0x18, 0x54, 0x98, 0xD8, 0x78, 0x00, 0x00,
45 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xC0, 0xB0, 0xA8,
46 0x78, 0x78, 0xB8, 0xD8, 0xFC, 0xF8, 0x00, 0x00,
49 u.c[0] = palblue[val];
50 u.c[1] = palgreen[val];
52 u.c[3] = back ? 0 : 0xFF;
55 p = ((u32int*)pic) + y * 3 * 3 * 256 + 3 * x;
56 for(Y = 0; Y < 3; Y++){
63 p = ((u32int*)pic) + y * 2 * 2 * 256 + 2 * x;
70 p = ((u32int*)pic) + y * 256 + x;
78 return pic[y * scale * scale * 256 * 4 + x * scale * 4 + 3] != 0;
82 pal(int c, int a, int spr)
85 return ppuread(0x3F00);
86 return ppuread(0x3F00 | ((a&3)<<2) | (c & 3) | (spr << 4));
94 if((ppuv & 0x7000) != 0x7000){
103 ppuv = (ppuv & 0x0C1F) | ((y & 31) << 5);
111 static u8int nr1, nr2, na;
112 static u32int r1, r2, a1, a2;
114 if(ppux >= 2 && ppux <= 257 || ppux >= 322 && ppux <= 337){
115 c = (r1 >> (15-ppusx)) & 1 | (r2 >> (14-ppusx)) & 2;
116 a = (a1 >> (15-ppusx)) & 1 | (a2 >> (14-ppusx)) & 2;
117 if(ppuy < 240 && ppux <= 257)
118 pixel(ppux-2, ppuy, pal(c, a, 0), c == 0);
124 if(ppux >= 256 && ppux <= 320){
128 ppuv = (ppuv & 0x7BE0) | (pput & 0x041F);
134 if((ppuv & 0x1f) == 0x1f){
142 t = ppuread(0x2000 | ppuv & 0x0FFF);
153 na = ppuread(0x23C0 | ppuv & 0x0C00 | ((ppuv & 0x0380) >> 4) | ((ppuv & 0x001C) >> 2));
154 if((ppuv & 0x0002) != 0) na >>= 2;
155 if((ppuv & 0x0040) != 0) na >>= 4;
158 nr1 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12);
161 nr2 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12 | 8);
170 int big, dx, dy, i, x, cc, pri;
172 static int n, m, nz, s0, t0;
173 static struct { u8int x, a; u16int t; } s[8], *sp;
174 static struct { u8int x, a, r1, r2; } t[8];
176 big = (mem[PPUCTRL] & BIGSPRITE) != 0;
179 for(p = oam, sp = s, n = 0; p < oam + sizeof(oam); p += 4){
180 if((dy = p[0]) >= 0xEF)
183 if(dy < 0 || dy >= (big ? 16 : 8))
190 if((sp->a & (1<<7)) != 0)
191 dy = (big ? 15 : 7) - dy;
193 sp->t |= (sp->t & 1) << 8;
200 sp->t |= (mem[PPUCTRL] & SPRTABLE) << 5;
201 sp->t = sp->t << 4 | dy;
207 if(ppux >= 2 && ppux <= 257 && m > 0){
210 if(t0 && dx >= 0 && dx < 8 && ppux != 257){
211 if((nz & 1) != 0 && iscolor(x, ppuy))
212 mem[PPUSTATUS] |= SPRITE0HIT;
217 for(i = m - 1; i >= 0; i--){
221 c = (t[i].r1 & 1) | (t[i].r2 & 1) << 1;
223 cc = pal(c, t[i].a & 3, 1);
224 pri = (t[i].a & (1<<5)) == 0;
229 if(cc != -1 && (pri || !iscolor(x, ppuy)))
230 pixel(x, ppuy, cc, 0);
233 for(i = 0; i < n; i++){
234 r1 = ppuread(s[i].t);
235 r2 = ppuread(s[i].t | 8);
236 if((s[i].a & (1<<6)) == 0){
237 r1 = ((r1 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
238 r2 = ((r2 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
246 nz = t[0].r1 | t[0].r2;
254 extern Rectangle picr;
255 extern Image *tmp, *bg;
260 while(nbrecv(mc->c, &m) > 0)
262 if(nbrecvul(mc->resizec) > 0){
263 if(getwindow(display, Refnone) < 0)
264 sysfatal("resize failed: %r");
265 p = divpt(addpt(screen->r.min, screen->r.max), 2);
266 picr = (Rectangle){subpt(p, Pt(scale * 128, scale * 120)), addpt(p, Pt(scale * 128, scale * 120))};
267 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
268 draw(screen, screen->r, bg, nil, ZP);
271 loadimage(tmp, tmp->r, pic, 256*240*4*scale*scale);
272 draw(screen, picr, tmp, nil, ZP);
274 loadimage(screen, picr, pic, 256*240*4*scale*scale);
275 flushimage(display, 1);
276 memset(pic, sizeof pic, 0);
285 if(ppuy < 240 || ppuy == 261){
287 if((mask & BGDISP) != 0)
289 if(((mask & BGDISP) == 0 && ppux <= 257 || ppux <= 10 && (mask & BG8DISP) == 0) && ppux >= 2)
290 pixel(ppux - 2, ppuy, ppuread(0x3F00), 1);
291 if((mask & SPRITEDISP) != 0 && ppuy != 261 && (ppux > 10 || (mask & SPRITE8DISP) != 0))
293 if(ppux == 240 && (mask & SPRITEDISP) != 0)
294 mapper[map](SCAN, 0);
297 mem[PPUSTATUS] &= ~(PPUVBLANK|SPRITE0HIT);
298 else if(ppux >= 280 && ppux <= 304 && (mask & BGDISP) != 0)
299 ppuv = (pput & 0x7BE0) | (ppuv & 0x041F);
301 }else if(ppuy == 241){
303 mem[PPUSTATUS] |= PPUVBLANK;
304 if((mem[PPUCTRL] & PPUNMI) != 0)
315 if(odd && (mem[PPUMASK] & (BGDISP | SPRITEDISP)) != 0)