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;
251 u16int otx, oty, otny;
255 bginit(int n, int nb, int prilo, int prihi)
261 p->szsh = (reg[BGMODE] & (1<<(4+n))) != 0 ? 4 : 3;
268 if(reg[MOSAIC] != 0 && (reg[MOSAIC] & (1<<n)) != 0){
269 p->msz = (reg[MOSAIC] >> 4) + 1;
271 sx -= p->mx = sx % p->msz;
277 p->tx = sx >> p->szsh;
278 p->tnx = sx & (p->sz - 1);
279 p->ty = sy >> p->szsh;
280 p->tny = sy & (p->sz - 1);
281 p->t = tile(n, p->tx, p->ty);
282 chr(n, nb, p->sz, p->t, p->tnx, p->tny, p->c);
283 p->pal = palette(n, p->t >> 10 & 7);
284 if((p->tnx & 7) != 0)
285 shift(p->c, nb, p->tnx & 7, p->t & 0x4000);
286 if(p->msz != 1 && p->mx != 0 && sx % p->msz == 0){
287 p->mv = bgpixel(p->c, nb, p->t & 0x4000);
288 if(p->tnx + p->mx >= 8){
292 shift(p->c, nb, p->mx - 1, p->t & 0x4000);
304 v = bgpixel(p->c, p->nb, p->t & 0x4000);
314 pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
315 if(++p->tnx == p->sz){
318 p->t = tile(n, p->tx, p->ty);
319 p->pal = palette(n, p->t >> 10 & 7);
321 if((p->tnx & 7) == 0)
322 chr(n, p->nb, p->sz, p->t, p->tnx, p->tny, p->c);
331 p->szsh = (reg[BGMODE] & (1<<6)) != 0 ? 4 : 3;
333 p->tnx = hofs[2] & (p->sz - 1);
334 p->tx = hofs[2] >> p->szsh;
335 bgctxts[0].otx = bgctxts[1].otx = 0xffff;
336 bgctxts[0].oty = bgctxts[0].ty;
337 bgctxts[0].otny = bgctxts[0].tny;
338 bgctxts[1].oty = bgctxts[1].ty;
339 bgctxts[1].otny = bgctxts[1].tny;
350 if(++p->tnx == p->sz){
352 hval = tile(2, p->tx, vofs[2] >> p->szsh);
353 if((hval & 0x8000) != 0){
359 hval = tile(2, p->tx, vofs[2] >> p->szsh);
360 vval = tile(2, p->tx, (vofs[2]+8) >> p->szsh);
362 sx = (rx & ~7) + (hval & 0x1ff8);
363 sy = ppuy + (vval & 0x1fff);
364 if((vval & 0x2000) != 0){
365 bgctxts[0].oty = sy >> bgctxts[0].szsh;
366 bgctxts[0].otny = sy & (bgctxts[0].sz - 1);
368 bgctxts[0].oty = bgctxts[0].ty;
369 bgctxts[0].otny = bgctxts[0].tny;
371 if((vval & 0x4000) != 0){
372 bgctxts[1].oty = sy >> bgctxts[1].szsh;
373 bgctxts[1].otny = sy & (bgctxts[1].sz - 1);
375 bgctxts[1].oty = bgctxts[1].ty;
376 bgctxts[1].otny = bgctxts[1].tny;
378 if((hval & 0x2000) != 0)
379 bgctxts[0].otx = sx >> bgctxts[0].szsh;
381 bgctxts[0].otx = 0xffff;
382 if((hval & 0x4000) != 0)
383 bgctxts[1].otx = sx >> bgctxts[1].szsh;
385 bgctxts[1].otx = 0xffff;
398 v = bgpixel(p->c, p->nb, p->t & 0x4000);
408 pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
409 if(++p->tnx == p->sz){
413 if((p->tnx & 7) == 0){
414 p->t = tile(n, p->otx == 0xffff ? p->tx : p->otx, p->oty);
415 p->pal = palette(n, p->t >> 10 & 7);
416 chr(n, p->nb, p->sz, p->t, p->tnx, p->otny, p->c);
430 if((reg[0x2105] & 7) != 7)
432 t = hofs[4] - m7[M7X];
433 if((t & 0x2000) != 0)
437 b7->x0 = (t * m7[M7A]) & ~63;
438 b7->y0 = (t * m7[M7C]) & ~63;
439 t = vofs[4] - m7[M7Y];
440 if((t & 0x2000) != 0)
444 b7->x0 += (t * m7[M7B]) & ~63;
445 b7->y0 += (t * m7[M7D]) & ~63;
446 b7->x0 += m7[M7X] << 8;
447 b7->y0 += m7[M7Y] << 8;
460 if((reg[MOSAIC] & 1) != 0){
461 p->msz = (reg[MOSAIC] >> 4) + 1;
466 if((reg[MOSAIC] & 2) != 0)
467 p->msz = (reg[MOSAIC] >> 4) + 1;
472 p->x = b7->x0 + ((m7[M7B] * y) & ~63);
473 p->y = b7->y0 + ((m7[M7D] * y) & ~63);
475 p->x += 255 * m7[M7A];
476 p->y += 255 * m7[M7C];
494 }else if(x > 1023 || y > 1023){
502 t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
504 v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
511 if(++p->mx == p->msz)
517 pixel(1, v & 0x7f, 0x71);
538 bginit(0, 2, 0x80, 0xb0);
539 bginit(1, 2, 0x71, 0xa1);
540 bginit(2, 2, 0x22, 0x52);
541 bginit(3, 2, 0x13, 0x43);
544 bginit(0, 4, 0x80, 0xb0);
545 bginit(1, 4, 0x71, 0xa1);
546 bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
549 bginit(0, 4, 0x40, 0xa0);
550 bginit(1, 4, 0x11, 0x71);
554 bginit(0, 8, 0x40, 0xa0);
555 bginit(1, 4, 0x11, 0x71);
558 bginit(0, 8, 0x40, 0xa0);
559 bginit(1, 2, 0x11, 0x71);
564 if((reg[SETINI] & EXTBG) != 0)
568 bgctxts[0].sz = bgctxts[1].sz = 0;
569 if(bitch[mode]++ == 0)
570 print("bg mode %d not implemented\n", mode);
601 if((reg[SETINI] & EXTBG) != 0)
612 u8int y, i, c, sx, sy;
617 u8int sx, i, c, pal, pri;
620 static u32int ch[34];
621 static u8int *p, q, over;
625 8, 8, 16, 16, 8, 8, 32, 32,
626 8, 8, 64, 64, 16, 16, 32, 32,
627 16, 16, 64, 64, 32, 32, 64, 64,
628 16, 32, 32, 64, 16, 32, 32, 32
630 static u16int base[2];
631 u8int dy, v, col, pri0, pri1, prio;
640 sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
641 base[0] = (reg[OBSEL] & 0x07) << 14;
642 base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
648 q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
651 sp->sy = sz[(q & 2) + 1];
657 if(sp->x < -(short)sp->sx && sp->x != -256)
667 sp->t1 = base[sp->c & 1];
676 if((reg[OAMADDH] & 0x80) != 0)
680 for(i = 0, tp = t; i < m; i++, tp++){
682 if(dx < 0 || dx >= tp->sx)
685 if((tp->c & 0x40) != 0){
686 v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
689 v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
694 nt = (tp->i - prio) & 0x7f;
695 if(v != 0 && nt < pri1){
702 pixel(OBJ, col, pri0);
707 for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
711 tp->pal = 0x80 | sp->c << 3 & 0x70;
712 tp->pri = 3 * (0x10 + (sp->c & 0x30));
721 if((sp->c & 0x80) != 0)
722 dy = sp->sy - 1 - dy;
723 a = sp->t0 | (dy & 7) << 1;
726 if(sp->x < 0 && (i = (-sp->x >> 3)) != 0){
727 if((sp->c & 0x40) != 0)
734 if((sp->c & 0x40) != 0){
736 for(i = 0; i < nt; i++){
737 if(cp < ch + nelem(ch)){
738 w = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
739 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
740 w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
741 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
748 for(i = 0; i < nt; i++){
749 if(cp < ch + nelem(ch)){
750 w = vram[sp->t1 | a & 0x1fff];
751 w |= vram[sp->t1 | ++a & 0x1fff] << 8;
752 w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
753 w |= vram[sp->t1 | ++a & 0x1fff] << 24;
760 if(sp->x < 0 && (i = (-sp->x) & 7) != 0)
761 if((sp->c & 0x40) != 0)
773 u16int v, w, r, g, b;
781 default: v = 1; break;
782 case 1: v = cw = window(COL); break;
783 case 2: v = !(cw = window(COL)); break;
784 case 3: v = 0; break;
787 if((pixelcol[0] & 0x10000) != 0)
790 v = cgram[pixelcol[0] & 0xff];
792 if((m2 & (1 << (pixelpri[0] & 0xf))) == 0)
794 switch((m >> 4) & 3){
796 case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
797 case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
800 div = (m2 & 0x40) != 0;
802 if((pixelcol[1] & 0x10000) != 0)
805 w = cgram[pixelcol[1] & 0xff];
806 div = div && (pixelpri[1] & 0xf) != COL;
809 if((m2 & 0x80) != 0){
810 r = (v & 0x7c00) - (w & 0x7c00);
811 g = (v & 0x03e0) - (w & 0x03e0);
812 b = (v & 0x001f) - (w & 0x001f);
813 if(r > 0x7c00) r = 0;
814 if(g > 0x03e0) g = 0;
815 if(b > 0x001f) b = 0;
817 r = (r >> 1) & 0xfc00;
818 g = (g >> 1) & 0xffe0;
823 r = (v & 0x7c00) + (w & 0x7c00);
824 g = (v & 0x03e0) + (w & 0x03e0);
825 b = (v & 0x001f) + (w & 0x001f);
827 r = (r >> 1) & 0xfc00;
828 g = (g >> 1) & 0xffe0;
831 if(r > 0x7c00) r = 0x7c00;
832 if(g > 0x03e0) g = 0x03e0;
833 if(b > 0x001f) b = 0x001f;
843 mode = reg[BGMODE] & 7;
844 bright = reg[INIDISP] & 0xf;
845 yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1;
847 if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){
849 if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
852 pixelcol[1] = 0x10000 | subcolor;
857 pixeldraw(rx, ppuy - 1, colormath());
859 pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x31c8 : 0);
862 if(ppux == 0x116 && ppuy <= yvbl)
864 if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy))
870 reg[RDNMI] &= ~VBLANK;
871 hdma = reg[0x420c]<<8;
877 reg[RDNMI] |= VBLANK;
878 if((reg[NMITIMEN] & VBLANK) != 0)
880 oamaddr = reg[0x2102] << 1 | (reg[0x2103] & 1) << 9;
881 if((reg[NMITIMEN] & AUTOJOY) != 0){
884 reg[0x4218] = keylatch >> 16;
885 reg[0x4219] = keylatch >> 24;
886 keylatch = keylatch << 16 | 0xffff;
889 if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)