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 u16int 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 if(ppuy < 240 && ppux <= 257){
117 a = (a1 >> (15-ppusx)) & 1 | (a2 >> (14-ppusx)) & 2;
118 pixel(ppux-2, ppuy, pal(c, a, 0), c == 0);
125 if(ppux >= 256 && ppux <= 320){
129 ppuv = (ppuv & 0x7BE0) | (pput & 0x041F);
135 if((ppuv & 0x1f) == 0x1f){
143 t = ppuread(0x2000 | ppuv & 0x0FFF);
154 na = ppuread(0x23C0 | ppuv & 0x0C00 | ((ppuv & 0x0380) >> 4) | ((ppuv & 0x001C) >> 2));
155 if((ppuv & 0x0002) != 0) na >>= 2;
156 if((ppuv & 0x0040) != 0) na >>= 4;
159 nr1 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12);
162 nr2 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12 | 8);
168 drawsprites(int show)
171 int big, dx, dy, i, x, cc, pri;
173 static int n, m, nz, s0, t0;
174 static struct { u8int x, a; u16int t; } s[8], *sp;
175 static struct { u8int x, a, r1, r2; } t[8];
177 big = (mem[PPUCTRL] & BIGSPRITE) != 0;
180 for(p = oam, sp = s, n = 0; p < oam + sizeof(oam); p += 4){
181 if((dy = p[0]) >= 0xEF)
184 if(dy < 0 || dy >= (big ? 16 : 8))
191 if((sp->a & (1<<7)) != 0)
192 dy = (big ? 15 : 7) - dy;
194 sp->t |= (sp->t & 1) << 8;
201 sp->t |= (mem[PPUCTRL] & SPRTABLE) << 5;
202 sp->t = sp->t << 4 | dy;
208 if(ppux >= 2 && ppux <= 257 && m > 0){
211 if(t0 && dx >= 0 && dx < 8 && ppux != 257){
212 if((nz & 1) != 0 && iscolor(x, ppuy) && show)
213 mem[PPUSTATUS] |= SPRITE0HIT;
218 for(i = m - 1; i >= 0; i--){
222 c = (t[i].r1 & 1) | (t[i].r2 & 1) << 1;
224 cc = pal(c, t[i].a & 3, 1);
225 pri = (t[i].a & (1<<5)) == 0;
230 if(cc != -1 && show && (pri || !iscolor(x, ppuy)))
231 pixel(x, ppuy, cc, 0);
234 for(i = 0; i < n; i++){
235 r1 = ppuread(s[i].t);
236 r2 = ppuread(s[i].t | 8);
237 if((s[i].a & (1<<6)) == 0){
238 r1 = ((r1 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
239 r2 = ((r2 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
247 nz = t[0].r1 | t[0].r2;
255 extern Rectangle picr;
256 extern Image *tmp, *bg;
258 static vlong old, delta;
267 while(nbrecv(mc->c, &m) > 0)
269 if(nbrecvul(mc->resizec) > 0){
270 if(getwindow(display, Refnone) < 0)
271 sysfatal("resize failed: %r");
272 p = divpt(addpt(screen->r.min, screen->r.max), 2);
273 picr = (Rectangle){subpt(p, Pt(scale * 128, scale * h/2)), addpt(p, Pt(scale * 128, scale * h/2))};
274 if(bg->chan != screen->chan){
276 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
278 draw(screen, screen->r, bg, nil, ZP);
280 if(screen->chan != tmp->chan || !rectinrect(picr, screen->r)){
281 loadimage(tmp, tmp->r, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale);
282 draw(screen, picr, tmp, nil, ZP);
284 loadimage(screen, picr, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale);
285 flushimage(display, 1);
286 memset(pic, sizeof pic, 0);
291 diff = BILLION/60 - (new - old) - delta;
297 diff = (old - new) - (diff / MILLION) * MILLION;
298 delta += (diff - delta) / 100;
309 if(ppuy < 240 || ppuy == 261){
311 if((mask & BGDISP) != 0)
313 if((((mask & BGDISP) == 0 && ppux <= 257 || ppux < 10 && (mask & BG8DISP) == 0) && ppux >= 2) && ppuy != 261)
314 pixel(ppux - 2, ppuy, ppuread(0x3F00), 1);
315 if((mask & SPRITEDISP) != 0 && ppuy != 261)
316 drawsprites(ppux >= 10 || (mask & SPRITE8DISP) != 0);
317 if(ppux == 240 && (mask & SPRITEDISP) != 0)
318 mapper[map](SCAN, 0);
321 mem[PPUSTATUS] &= ~(PPUVBLANK|SPRITE0HIT);
322 else if(ppux >= 280 && ppux <= 304 && (mask & BGDISP) != 0)
323 ppuv = (pput & 0x7BE0) | (ppuv & 0x041F);
325 }else if(ppuy == 241){
327 mem[PPUSTATUS] |= PPUVBLANK;
328 if((mem[PPUCTRL] & PPUNMI) != 0)
339 if(odd && (mem[PPUMASK] & (BGDISP | SPRITEDISP)) != 0)