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);
283 if((p->tnx & 7) != 0)
284 shift(p->c, nb, p->tnx & 7, 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;
370 if((reg[MOSAIC] & 2) != 0)
371 p->msz = (reg[MOSAIC] >> 4) + 1;
376 p->x = b7->x0 + ((m7[M7B] * y) & ~63);
377 p->y = b7->y0 + ((m7[M7D] * y) & ~63);
379 p->x += 255 * m7[M7A];
380 p->y += 255 * m7[M7C];
398 }else if(x > 1023 || y > 1023){
406 t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
408 v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
415 if(++p->mx == p->msz)
421 pixel(1, v & 0x7f, 0x71);
442 bginit(0, 2, 0x80, 0xb0);
443 bginit(1, 2, 0x71, 0xa1);
444 bginit(2, 2, 0x22, 0x52);
445 bginit(3, 2, 0x13, 0x43);
448 bginit(0, 4, 0x80, 0xb0);
449 bginit(1, 4, 0x71, 0xa1);
450 bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
453 bginit(0, 4, 0x40, 0xa0);
454 bginit(1, 4, 0x11, 0x71);
457 bginit(0, 8, 0x40, 0xa0);
458 bginit(1, 4, 0x11, 0x71);
462 if((reg[SETINI] & EXTBG) != 0)
466 bgctxts[0].sz = bgctxts[1].sz = 0;
467 if(bitch[mode]++ == 0)
468 print("bg mode %d not implemented\n", mode);
494 if((reg[SETINI] & EXTBG) != 0)
505 u8int y, i, c, sx, sy;
510 u8int sx, i, c, pal, pri;
513 static u32int ch[34];
514 static u8int *p, q, over;
518 8, 8, 16, 16, 8, 8, 32, 32,
519 8, 8, 64, 64, 16, 16, 32, 32,
520 16, 16, 64, 64, 32, 32, 64, 64,
521 16, 32, 32, 64, 16, 32, 32, 32
523 static u16int base[2];
524 u8int dy, v, col, pri0, pri1, prio;
533 sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
534 base[0] = (reg[OBSEL] & 0x07) << 14;
535 base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
541 q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
544 sp->sy = sz[(q & 2) + 1];
550 if(sp->x < -(short)sp->sx && sp->x != -256)
560 sp->t1 = base[sp->c & 1];
569 if((reg[OAMADDH] & 0x80) != 0)
573 for(i = 0, tp = t; i < m; i++, tp++){
575 if(dx < 0 || dx >= tp->sx)
578 if((tp->c & 0x40) != 0){
579 v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
582 v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
587 nt = (tp->i - prio) & 0x7f;
588 if(v != 0 && nt < pri1){
595 pixel(OBJ, col, pri0);
600 for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
604 tp->pal = 0x80 | sp->c << 3 & 0x70;
605 tp->pri = 3 * (0x10 + (sp->c & 0x30));
614 if((sp->c & 0x80) != 0)
615 dy = sp->sy - 1 - dy;
616 a = sp->t0 | (dy & 7) << 1;
619 if((sp->c & 0x40) != 0){
621 for(i = 0; i < nt; i++){
622 if(cp < ch + nelem(ch)){
623 w = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
624 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
625 w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
626 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
633 for(i = 0; i < nt; i++){
634 if(cp < ch + nelem(ch)){
635 w = vram[sp->t1 | a & 0x1fff];
636 w |= vram[sp->t1 | ++a & 0x1fff] << 8;
637 w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
638 w |= vram[sp->t1 | ++a & 0x1fff] << 24;
653 u16int v, w, r, g, b;
661 default: v = 1; break;
662 case 1: v = cw = window(COL); break;
663 case 2: v = !(cw = window(COL)); break;
664 case 3: v = 0; break;
667 if((pixelcol[0] & 0x10000) != 0)
670 v = cgram[pixelcol[0] & 0xff];
672 if((m2 & (1 << (pixelpri[0] & 0xf))) == 0)
674 switch((m >> 4) & 3){
676 case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
677 case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
680 div = (m2 & 0x40) != 0;
682 if((pixelcol[1] & 0x10000) != 0)
685 w = cgram[pixelcol[1] & 0xff];
686 div = div && (pixelpri[1] & 0xf) != COL;
689 if((m2 & 0x80) != 0){
690 r = (v & 0x7c00) - (w & 0x7c00);
691 g = (v & 0x03e0) - (w & 0x03e0);
692 b = (v & 0x001f) - (w & 0x001f);
693 if(r > 0x7c00) r = 0;
694 if(g > 0x03e0) g = 0;
695 if(b > 0x001f) b = 0;
697 r = (r >> 1) & 0xfc00;
698 g = (g >> 1) & 0xffe0;
703 r = (v & 0x7c00) + (w & 0x7c00);
704 g = (v & 0x03e0) + (w & 0x03e0);
705 b = (v & 0x001f) + (w & 0x001f);
707 r = (r >> 1) & 0xfc00;
708 g = (g >> 1) & 0xffe0;
711 if(r > 0x7c00) r = 0x7c00;
712 if(g > 0x03e0) g = 0x03e0;
713 if(b > 0x001f) b = 0x001f;
723 mode = reg[BGMODE] & 7;
724 bright = reg[INIDISP] & 0xf;
725 yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1;
727 if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){
729 if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
732 pixelcol[1] = 0x10000 | subcolor;
737 pixeldraw(rx, ppuy - 1, colormath());
739 pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x31c8 : 0);
742 if(ppux == 0x116 && ppuy <= yvbl)
744 if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy))
750 reg[RDNMI] &= ~VBLANK;
751 hdma = reg[0x420c]<<8;
757 reg[RDNMI] |= VBLANK;
758 if((reg[NMITIMEN] & VBLANK) != 0)
760 if((reg[NMITIMEN] & AUTOJOY) != 0){
763 reg[0x4218] = keylatch >> 16;
764 reg[0x4219] = keylatch >> 24;
765 keylatch = keylatch << 16 | 0xffff;
768 if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)