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;
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;
215 for(i = m - 1; i >= 0; i--){
219 c = (t[i].r1 & 1) | (t[i].r2 & 1) << 1;
221 if((t[i].a & (1<<5)) == 0 || !iscolor(x, ppuy))
222 pixel(x, ppuy, pal(c, t[i].a & 3, 1), 0);
229 for(i = 0; i < n; i++){
230 r1 = ppuread(s[i].t);
231 r2 = ppuread(s[i].t | 8);
232 if((s[i].a & (1<<6)) == 0){
233 r1 = ((r1 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
234 r2 = ((r2 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
242 nz = t[0].r1 | t[0].r2;
250 extern Rectangle picr;
251 extern Image *tmp, *bg;
256 while(nbrecv(mc->c, &m) > 0)
258 if(nbrecvul(mc->resizec) > 0){
259 if(getwindow(display, Refnone) < 0)
260 sysfatal("resize failed: %r");
261 p = divpt(addpt(screen->r.min, screen->r.max), 2);
262 picr = (Rectangle){subpt(p, Pt(scale * 128, scale * 120)), addpt(p, Pt(scale * 128, scale * 120))};
263 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
264 draw(screen, screen->r, bg, nil, ZP);
267 loadimage(tmp, tmp->r, pic, 256*240*4*scale*scale);
268 draw(screen, picr, tmp, nil, ZP);
270 loadimage(screen, picr, pic, 256*240*4*scale*scale);
271 flushimage(display, 1);
272 memset(pic, sizeof pic, 0);
281 if(ppuy < 240 || ppuy == 261){
282 bg = (mem[PPUMASK] & BGDISP) != 0;
285 if((mem[PPUMASK] & SPRITEDISP) != 0 && ppuy != 261)
289 mem[PPUSTATUS] &= ~(PPUVBLANK|SPRITE0HIT);
290 else if(ppux >= 280 && ppux <= 304 && bg)
291 ppuv = (pput & 0x7BE0) | (ppuv & 0x041F);
293 }else if(ppuy == 241){
295 mem[PPUSTATUS] |= PPUVBLANK;
296 if((mem[PPUCTRL] & PPUNMI) != 0)
307 if(odd && (mem[PPUCTRL] & (BGDISP | SPRITEDISP)) != 0)