8 static u8int mode, bright, pixelpri[2];
9 static u32int pixelcol[2];
10 u16int vtime = 0x1ff, htime = 0x1ff, subcolor, mosatop;
11 uchar pic[256*239*2*9];
12 u16int hofs[5], vofs[5];
24 enum { OBJ = 4, COL = 5, OBJNC = 8 };
37 return r << 10 | g << 5 | b;
41 pixeldraw(int x, int y, u16int v)
45 union { u16int w; u8int b[2]; } u;
51 p = pic + (x + y * 256) * 2;
59 q = (u16int*)pic + (x + y * 256 * 2) * 2;
66 q = (u16int*)pic + (x + y * 256 * 3) * 3;
67 for(i = 0; i < 3; i++){
81 a = reg[0x2123 + (n >> 1)];
84 if((a & (WIN1|WIN2)) == 0)
86 w1 = rx >= reg[0x2126] && rx <= reg[0x2127];
87 w2 = rx >= reg[0x2128] && rx <= reg[0x2129];
92 if((a & (WIN1|WIN2)) != (WIN1|WIN2))
93 return (a & WIN1) != 0 ? w1 : w2;
94 a = reg[0x212a + (n >> 2)] >> ((n & 3) << 1);
96 case 1: return w1 & w2;
97 case 2: return w1 ^ w2;
98 case 3: return w1 ^ w2 ^ 1;
104 pixel(int n, int v, int pri)
109 if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
113 if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
120 tile(int n, int tx, int ty)
127 ta = ((a & ~3) << 9) + ((tx & 0x1f) << 1) + ((ty & 0x1f) << 6);
129 ta += (tx & 0x20) << 6;
131 ta += (ty & 0x20) << (6 + (a & 1));
133 return t | vram[ta] << 8;
137 chr(int n, int nb, int sz, u16int t, int x, int y, u32int c[])
143 t += ((x >> 3 ^ t >> 14) & 1) + ((~t >> 11) & 16);
146 t += ((x >> 3 ^ t >> 14) & 1) + ((t >> 11) & 16);
148 if((t & 0x8000) != 0)
150 a = reg[0x210b + (n >> 1)];
155 a = (a << 13) + (t & 0x3ff) * 8 * nb + y * 2;
157 c[0] |= vram[a] << 8;
160 c[0] |= vram[a++] << 16;
161 c[0] |= vram[a] << 24;
165 c[1] |= vram[a] << 8;
167 c[1] |= vram[a++] << 16;
168 c[1] |= vram[a] << 24;
174 palette(int n, int p)
178 return p << 2 | n << 5;
195 if((reg[CGWSEL] & DIRCOL) != 0)
202 shift(u32int *c, int nb, int n, int d)
216 bgpixel(u32int *c, int nb, int d)
221 v = c[0] & 1 | c[0] >> 7 & 2;
223 v |= c[0] >> 14 & 4 | c[0] >> 21 & 8;
225 v |= c[1] << 4 & 16 | c[1] >> 3 & 32 | c[1] >> 10 & 64 | c[1] >> 17 & 128;
231 v = c[0] >> 7 & 1 | c[0] >> 14 & 2;
233 v |= c[0] >> 21 & 4 | c[0] >> 28 & 8;
235 v |= c[1] >> 3 & 16 | c[1] >> 10 & 32 | c[1] >> 17 & 64 | c[1] >> 24 & 128;
244 static struct bgctxt {
245 u8int sz, szsh, nb, pri[2];
246 u16int tx, ty, tnx, tny;
254 bginit(int n, int nb, int prilo, int prihi)
260 p->szsh = (reg[BGMODE] & (1<<(4+n))) != 0 ? 4 : 3;
267 if(reg[MOSAIC] != 0 && (reg[MOSAIC] & (1<<n)) != 0){
268 p->msz = (reg[MOSAIC] >> 4) + 1;
270 sx -= p->mx = sx % p->msz;
276 p->tx = sx >> p->szsh;
277 p->tnx = sx & (p->sz - 1);
278 p->ty = sy >> p->szsh;
279 p->tny = sy & (p->sz - 1);
280 p->t = tile(n, p->tx, p->ty);
281 chr(n, nb, p->sz, p->t, p->tnx, p->tny, p->c);
282 p->pal = palette(n, p->t >> 10 & 7);
284 shift(p->c, nb, p->tnx, p->t & 0x4000);
285 if(p->msz != 1 && p->mx != 0 && sx % p->msz == 0){
286 p->mv = bgpixel(p->c, nb, p->t & 0x4000);
287 if(p->tnx + p->mx >= 8){
291 shift(p->c, nb, p->mx - 1, p->t & 0x4000);
303 v = bgpixel(p->c, p->nb, p->t & 0x4000);
313 pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
314 if(++p->tnx == p->sz){
317 p->t = tile(n, p->tx, p->ty);
318 p->pal = palette(n, p->t >> 10 & 7);
320 if((p->tnx & 7) == 0)
321 chr(n, p->nb, p->sz, p->t, p->tnx, p->tny, p->c);
334 if((reg[0x2105] & 7) != 7)
336 t = hofs[4] - m7[M7X];
337 if((t & 0x2000) != 0)
341 b7->x0 = (t * m7[M7A]) & ~63;
342 b7->y0 = (t * m7[M7C]) & ~63;
343 t = vofs[4] - m7[M7Y];
344 if((t & 0x2000) != 0)
348 b7->x0 += (t * m7[M7B]) & ~63;
349 b7->y0 += (t * m7[M7D]) & ~63;
350 b7->x0 += m7[M7X] << 8;
351 b7->y0 += m7[M7Y] << 8;
364 if((reg[MOSAIC] & 1) != 0){
365 p->msz = (reg[MOSAIC] >> 4) + 1;
369 if(n == 1 && (reg[MOSAIC] & 2) != 0)
370 p->msz = (reg[MOSAIC] >> 4) + 1;
373 p->x = b7->x0 + ((m7[M7B] * y) & ~63);
374 p->y = b7->y0 + ((m7[M7D] * y) & ~63);
376 p->x += 255 * m7[M7A];
377 p->y += 255 * m7[M7C];
395 }else if(x > 1023 || y > 1023){
403 t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
405 v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
412 if(++p->mx == p->msz)
417 pixel(1, v & 0x7f, 0x71);
438 bginit(0, 2, 0x80, 0xb0);
439 bginit(1, 2, 0x71, 0xa1);
440 bginit(2, 2, 0x22, 0x52);
441 bginit(3, 2, 0x13, 0x43);
444 bginit(0, 4, 0x80, 0xb0);
445 bginit(1, 4, 0x71, 0xa1);
446 bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
449 bginit(0, 4, 0x40, 0xa0);
450 bginit(1, 4, 0x11, 0x71);
453 bginit(0, 8, 0x40, 0xa0);
454 bginit(1, 4, 0x11, 0x71);
458 if((reg[SETINI] & EXTBG) != 0)
462 bgctxts[0].sz = bgctxts[1].sz = 0;
463 if(bitch[mode]++ == 0)
464 print("bg mode %d not implemented\n", mode);
490 if((reg[SETINI] & EXTBG) != 0)
501 u8int y, i, c, sx, sy;
506 u8int sx, i, c, pal, pri;
509 static u32int ch[34];
510 static u8int *p, q, over;
514 8, 8, 16, 16, 8, 8, 32, 32,
515 8, 8, 64, 64, 16, 16, 32, 32,
516 16, 16, 64, 64, 32, 32, 64, 64,
517 16, 32, 32, 64, 16, 32, 32, 32
519 static u16int base[2];
520 u8int dy, v, col, pri0, pri1, prio;
529 sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
530 base[0] = (reg[OBSEL] & 0x07) << 14;
531 base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
537 q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
540 sp->sy = sz[(q & 2) + 1];
546 if(sp->x < -(short)sp->sx && sp->x != -256)
556 sp->t1 = base[sp->c & 1];
565 if((reg[OAMADDH] & 0x80) != 0)
569 for(i = 0, tp = t; i < m; i++, tp++){
571 if(dx < 0 || dx >= tp->sx)
574 if((tp->c & 0x40) != 0){
575 v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
578 v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
583 nt = (tp->i - prio) & 0x7f;
584 if(v != 0 && nt < pri1){
591 pixel(OBJ, col, pri0);
596 for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
600 tp->pal = 0x80 | sp->c << 3 & 0x70;
601 tp->pri = 3 * (0x10 + (sp->c & 0x30));
610 if((sp->c & 0x80) != 0)
611 dy = sp->sy - 1 - dy;
612 a = sp->t0 | (dy & 7) << 1;
615 if((sp->c & 0x40) != 0){
617 for(i = 0; i < nt; i++){
618 if(cp < ch + nelem(ch)){
619 w = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
620 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
621 w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
622 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
629 for(i = 0; i < nt; i++){
630 if(cp < ch + nelem(ch)){
631 w = vram[sp->t1 | a & 0x1fff];
632 w |= vram[sp->t1 | ++a & 0x1fff] << 8;
633 w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
634 w |= vram[sp->t1 | ++a & 0x1fff] << 24;
649 u16int v, w, r, g, b;
657 default: v = 1; break;
658 case 1: v = cw = window(COL); break;
659 case 2: v = !(cw = window(COL)); break;
660 case 3: v = 0; break;
663 if((pixelcol[0] & 0x10000) != 0)
666 v = cgram[pixelcol[0] & 0xff];
668 if((m2 & (1 << (pixelpri[0] & 0xf))) == 0)
670 switch((m >> 4) & 3){
672 case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
673 case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
676 div = (m2 & 0x40) != 0;
678 if((pixelcol[1] & 0x10000) != 0)
681 w = cgram[pixelcol[1] & 0xff];
682 div = div && (pixelpri[1] & 0xf) != COL;
685 if((m2 & 0x80) != 0){
686 r = (v & 0x7c00) - (w & 0x7c00);
687 g = (v & 0x03e0) - (w & 0x03e0);
688 b = (v & 0x001f) - (w & 0x001f);
689 if(r > 0x7c00) r = 0;
690 if(g > 0x03e0) g = 0;
691 if(b > 0x001f) b = 0;
693 r = (r >> 1) & 0xfc00;
694 g = (g >> 1) & 0xffe0;
699 r = (v & 0x7c00) + (w & 0x7c00);
700 g = (v & 0x03e0) + (w & 0x03e0);
701 b = (v & 0x001f) + (w & 0x001f);
703 r = (r >> 1) & 0xfc00;
704 g = (g >> 1) & 0xffe0;
707 if(r > 0x7c00) r = 0x7c00;
708 if(g > 0x03e0) g = 0x03e0;
709 if(b > 0x001f) b = 0x001f;
719 mode = reg[BGMODE] & 7;
720 bright = reg[INIDISP] & 0xf;
721 yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1;
723 if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){
725 if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
728 pixelcol[1] = 0x10000 | subcolor;
733 pixeldraw(rx, ppuy - 1, colormath());
735 pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x31c8 : 0);
738 if(ppux == 0x116 && ppuy <= yvbl)
740 if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy))
746 reg[RDNMI] &= ~VBLANK;
747 hdma = reg[0x420c]<<8;
753 reg[RDNMI] |= VBLANK;
754 if((reg[NMITIMEN] & VBLANK) != 0)
756 if((reg[NMITIMEN] & AUTOJOY) != 0){
759 reg[0x4218] = keylatch >> 16;
760 reg[0x4219] = keylatch >> 24;
761 keylatch = keylatch << 16 | 0xffff;
764 if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)