8 static u8int mode, bright, pixelpri[2], hires;
9 static u32int pixelcol[2];
10 u16int vtime = 0x1ff, htime = 0x1ff, subcolor;
11 uchar pic[256*239*2*3];
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, int s)
45 union { u16int w; u8int b[2]; } u;
47 if(bright != 0xf && s >= 0)
50 p = pic + (x + y * 256) * 2;
58 q = (u16int*)pic + (x + y * 256) * 2;
63 q = (u16int*)pic + (x + y * 256) * 3;
75 a = reg[0x2123 + (n >> 1)];
78 if((a & (WIN1|WIN2)) == 0)
80 w1 = rx >= reg[0x2126] && rx <= reg[0x2127];
81 w2 = rx >= reg[0x2128] && rx <= reg[0x2129];
86 if((a & (WIN1|WIN2)) != (WIN1|WIN2))
87 return (a & WIN1) != 0 ? w1 : w2;
88 a = reg[0x212a + (n >> 2)] >> ((n & 3) << 1);
90 case 1: return w1 & w2;
91 case 2: return w1 ^ w2;
92 case 3: return w1 ^ w2 ^ 1;
98 npixel(int n, int v, int pri)
103 if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
107 if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
114 spixel(int n, int v, int pri)
119 if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
126 mpixel(int n, int v, int pri)
131 if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
137 static void (*pixel)(int, int, int) = npixel;
140 tile(int n, int tx, int ty)
147 ta = ((a & ~3) << 9) + ((tx & 0x1f) << 1) + ((ty & 0x1f) << 6);
149 ta += (tx & 0x20) << 6;
151 ta += (ty & 0x20) << (6 + (a & 1));
153 return t | vram[ta] << 8;
157 chr(int n, int nb, int w, int h, u16int t, int x, int y, u32int c[])
162 t += (x >> 3 ^ t >> 14) & 1;
165 t += (~t >> 11) & 16;
170 if((t & 0x8000) != 0)
172 a = reg[0x210b + (n >> 1)];
177 a = (a << 13) + (t & 0x3ff) * 8 * nb + y * 2;
179 c[0] |= vram[a] << 8;
182 c[0] |= vram[a++] << 16;
183 c[0] |= vram[a] << 24;
187 c[1] |= vram[a] << 8;
189 c[1] |= vram[a++] << 16;
190 c[1] |= vram[a] << 24;
196 palette(int n, int p)
200 return p << 2 | n << 5;
217 if((reg[CGWSEL] & DIRCOL) != 0)
224 shift(u32int *c, int nb, int n, int d)
238 bgpixel(u32int *c, int nb, int d)
243 v = c[0] & 1 | c[0] >> 7 & 2;
245 v |= c[0] >> 14 & 4 | c[0] >> 21 & 8;
247 v |= c[1] << 4 & 16 | c[1] >> 3 & 32 | c[1] >> 10 & 64 | c[1] >> 17 & 128;
253 v = c[0] >> 7 & 1 | c[0] >> 14 & 2;
255 v |= c[0] >> 21 & 4 | c[0] >> 28 & 8;
257 v |= c[1] >> 3 & 16 | c[1] >> 10 & 32 | c[1] >> 17 & 64 | c[1] >> 24 & 128;
266 static struct bgctxt {
267 u8int w, h, wsh, hsh, nb, pri[2];
268 u16int tx, ty, tnx, tny;
273 u16int otx, oty, otny;
277 bginit(int n, int nb, int prilo, int prihi)
283 p->hsh = ((reg[BGMODE] & (1<<(4+n))) != 0) ? 4 : 3;
284 p->wsh = mode >= 5 ? 4 : p->hsh;
292 if(reg[MOSAIC] != 0 && (reg[MOSAIC] & (1<<n)) != 0){
293 p->msz = (reg[MOSAIC] >> 4) + 1;
295 sx -= p->mx = sx % p->msz;
303 p->tx = sx >> p->wsh;
304 p->tnx = sx & (p->w - 1);
305 p->ty = sy >> p->hsh;
306 p->tny = sy & (p->h - 1);
307 p->t = tile(n, p->tx, p->ty);
308 chr(n, nb, p->w, p->h, p->t, p->tnx, p->tny, p->c);
309 p->pal = palette(n, p->t >> 10 & 7);
310 if((p->tnx & 7) != 0)
311 shift(p->c, nb, p->tnx & 7, p->t & 0x4000);
312 if(p->msz != 1 && p->mx != 0 && sx % p->msz == 0){
313 p->mv = bgpixel(p->c, nb, p->t & 0x4000);
314 if(p->tnx + p->mx >= 8){
318 shift(p->c, nb, p->mx - 1, p->t & 0x4000);
330 v = bgpixel(p->c, p->nb, p->t & 0x4000);
340 pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
341 if(++p->tnx == p->w){
344 p->t = tile(n, p->tx, p->ty);
345 p->pal = palette(n, p->t >> 10 & 7);
347 if((p->tnx & 7) == 0)
348 chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->tny, p->c);
357 p->hsh = (reg[BGMODE] & (1<<6)) != 0 ? 4 : 3;
358 p->wsh = mode >= 5 ? 4 : p->hsh;
361 p->tnx = hofs[2] & (p->w - 1);
362 p->tx = hofs[2] >> p->wsh;
363 bgctxts[0].otx = bgctxts[1].otx = 0xffff;
364 bgctxts[0].oty = bgctxts[0].ty;
365 bgctxts[0].otny = bgctxts[0].tny;
366 bgctxts[1].oty = bgctxts[1].ty;
367 bgctxts[1].otny = bgctxts[1].tny;
378 if(++p->tnx == p->w){
380 hval = tile(2, p->tx, vofs[2] >> p->hsh);
381 if((hval & 0x8000) != 0){
387 hval = tile(2, p->tx, vofs[2] >> p->hsh);
388 vval = tile(2, p->tx, (vofs[2]+8) >> p->hsh);
390 sx = (rx & ~7) + (hval & 0x1ff8);
391 sy = ppuy + (vval & 0x1fff);
392 if((vval & 0x2000) != 0){
393 bgctxts[0].oty = sy >> bgctxts[0].hsh;
394 bgctxts[0].otny = sy & (bgctxts[0].h - 1);
396 bgctxts[0].oty = bgctxts[0].ty;
397 bgctxts[0].otny = bgctxts[0].tny;
399 if((vval & 0x4000) != 0){
400 bgctxts[1].oty = sy >> bgctxts[1].hsh;
401 bgctxts[1].otny = sy & (bgctxts[1].h - 1);
403 bgctxts[1].oty = bgctxts[1].ty;
404 bgctxts[1].otny = bgctxts[1].tny;
406 if((hval & 0x2000) != 0)
407 bgctxts[0].otx = sx >> bgctxts[0].wsh;
409 bgctxts[0].otx = 0xffff;
410 if((hval & 0x4000) != 0)
411 bgctxts[1].otx = sx >> bgctxts[1].wsh;
413 bgctxts[1].otx = 0xffff;
426 v = bgpixel(p->c, p->nb, p->t & 0x4000);
436 pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
437 if(++p->tnx == p->w){
441 if((p->tnx & 7) == 0){
442 p->t = tile(n, p->otx == 0xffff ? p->tx : p->otx, p->oty);
443 p->pal = palette(n, p->t >> 10 & 7);
444 chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->otny, p->c);
458 if((reg[0x2105] & 7) != 7)
460 t = hofs[4] - m7[M7X];
461 if((t & 0x2000) != 0)
465 b7->x0 = (t * m7[M7A]) & ~63;
466 b7->y0 = (t * m7[M7C]) & ~63;
467 t = vofs[4] - m7[M7Y];
468 if((t & 0x2000) != 0)
472 b7->x0 += (t * m7[M7B]) & ~63;
473 b7->y0 += (t * m7[M7D]) & ~63;
474 b7->x0 += m7[M7X] << 8;
475 b7->y0 += m7[M7Y] << 8;
488 if((reg[MOSAIC] & 1) != 0){
489 p->msz = (reg[MOSAIC] >> 4) + 1;
494 if((reg[MOSAIC] & 2) != 0)
495 p->msz = (reg[MOSAIC] >> 4) + 1;
500 p->x = b7->x0 + ((m7[M7B] * y) & ~63);
501 p->y = b7->y0 + ((m7[M7D] * y) & ~63);
503 p->x += 255 * m7[M7A];
504 p->y += 255 * m7[M7C];
522 }else if(x > 1023 || y > 1023){
530 t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
532 v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
539 if(++p->mx == p->msz)
545 pixel(1, v & 0x7f, 0x71);
567 bginit(0, 2, 0x80, 0xb0);
568 bginit(1, 2, 0x71, 0xa1);
569 bginit(2, 2, 0x22, 0x52);
570 bginit(3, 2, 0x13, 0x43);
573 bginit(0, 4, 0x80, 0xb0);
574 bginit(1, 4, 0x71, 0xa1);
575 bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
578 bginit(0, 4, 0x40, 0xa0);
579 bginit(1, 4, 0x11, 0x71);
583 bginit(0, 8, 0x40, 0xa0);
584 bginit(1, 4, 0x11, 0x71);
587 bginit(0, 8, 0x40, 0xa0);
588 bginit(1, 2, 0x11, 0x71);
592 bginit(0, 4, 0x40, 0xa0);
593 bginit(1, 2, 0x11, 0x71);
596 bginit(0, 4, 0x40, 0xa0);
601 if((reg[SETINI] & EXTBG) != 0)
605 bgctxts[0].w = bgctxts[1].w = 0;
606 if(bitch[mode]++ == 0)
607 print("bg mode %d not implemented\n", mode);
655 if((reg[SETINI] & EXTBG) != 0)
666 u8int y, i, c, sx, sy;
671 u8int sx, i, c, pal, pri;
674 static u32int ch[34];
679 8, 8, 16, 16, 8, 8, 32, 32,
680 8, 8, 64, 64, 16, 16, 32, 32,
681 16, 16, 64, 64, 32, 32, 64, 64,
682 16, 32, 32, 64, 16, 32, 32, 32
684 static u16int base[2];
685 u8int dy, v, col, pri0, pri1, prio;
693 sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
694 base[0] = (reg[OBSEL] & 0x07) << 14;
695 base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
701 q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
704 sp->sy = sz[(q & 2) + 1];
710 if(sp->x <= -(short)sp->sx && sp->x != -256)
720 sp->t1 = base[sp->c & 1];
729 if((reg[OAMADDH] & 0x80) != 0)
733 for(i = 0, tp = t; i < m; i++, tp++){
735 if(dx < 0 || dx >= tp->sx)
738 if((tp->c & 0x40) != 0){
739 v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
742 v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
747 nt = (tp->i - prio) & 0x7f;
748 if(v != 0 && nt < pri1){
755 pixel(OBJ, col, pri0);
760 for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
764 tp->pal = 0x80 | sp->c << 3 & 0x70;
765 tp->pri = 3 * (0x10 + (sp->c & 0x30));
774 if((sp->c & 0x80) != 0)
775 dy = sp->sy - 1 - dy;
776 a = sp->t0 | (dy & 7) << 1;
779 if(sp->x < 0 && (i = (-sp->x >> 3)) != 0){
780 if((sp->c & 0x40) != 0)
787 if((sp->c & 0x40) != 0){
789 for(i = 0; i < nt; i++){
790 if(cp < ch + nelem(ch)){
791 w = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
792 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
793 w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
794 w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
801 for(i = 0; i < nt; i++){
802 if(cp < ch + nelem(ch)){
803 w = vram[sp->t1 | a & 0x1fff];
804 w |= vram[sp->t1 | ++a & 0x1fff] << 8;
805 w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
806 w |= vram[sp->t1 | ++a & 0x1fff] << 24;
813 if(sp->x < 0 && (i = (-sp->x) & 7) != 0)
814 if((sp->c & 0x40) != 0)
825 u16int v, w, r, g, b;
833 default: v = 1; break;
834 case 1: v = cw = window(COL); break;
835 case 2: v = !(cw = window(COL)); break;
836 case 3: v = 0; break;
839 if((pixelcol[n] & 0x10000) != 0)
842 v = cgram[pixelcol[n] & 0xff];
844 if((m2 & (1 << (pixelpri[n] & 0xf))) == 0)
846 switch((m >> 4) & 3){
848 case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
849 case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
852 div = (m2 & 0x40) != 0;
854 if((pixelcol[1-n] & 0x10000) != 0)
857 w = cgram[pixelcol[1-n] & 0xff];
858 div = div && (pixelpri[1-n] & 0xf) != COL;
861 if((m2 & 0x80) != 0){
862 r = (v & 0x7c00) - (w & 0x7c00);
863 g = (v & 0x03e0) - (w & 0x03e0);
864 b = (v & 0x001f) - (w & 0x001f);
865 if(r > 0x7c00) r = 0;
866 if(g > 0x03e0) g = 0;
867 if(b > 0x001f) b = 0;
869 r = (r >> 1) & 0xfc00;
870 g = (g >> 1) & 0xffe0;
875 r = (v & 0x7c00) + (w & 0x7c00);
876 g = (v & 0x03e0) + (w & 0x03e0);
877 b = (v & 0x001f) + (w & 0x001f);
879 r = (r >> 1) & 0xfc00;
880 g = (g >> 1) & 0xffe0;
883 if(r > 0x7c00) r = 0x7c00;
884 if(g > 0x03e0) g = 0x03e0;
885 if(b > 0x001f) b = 0x001f;
895 mode = reg[BGMODE] & 7;
896 bright = reg[INIDISP] & 0xf;
897 hires = mode >= 5 && mode < 7 || (reg[SETINI] & 8) != 0;
898 yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1;
900 if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){
902 if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
905 pixelcol[1] = 0x10000 | subcolor;
911 pixeldraw(rx, ppuy - 1, colormath(1), 0);
912 pixeldraw(rx, ppuy - 1, colormath(0), 1);
914 pixeldraw(rx, ppuy - 1, colormath(0), 0);
916 pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x6739 : 0, -1);
921 if(ppux == 0x116 && ppuy <= yvbl)
923 if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime+4 == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy))
929 reg[RDNMI] &= ~VBLANK;
932 hdma = reg[0x420c]<<8;
938 reg[RDNMI] |= VBLANK;
939 if((reg[NMITIMEN] & VBLANK) != 0)
941 if((reg[INIDISP] & 0x80) == 0)
942 oamaddr = reg[0x2102] << 1 | (reg[0x2103] & 1) << 9;
943 if((reg[NMITIMEN] & AUTOJOY) != 0){
946 reg[0x4218] = keylatch >> 16;
947 reg[0x4219] = keylatch >> 24;
948 keylatch = keylatch << 16 | 0xffff;
951 if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)