8 u8int bldy, blda, bldb;
14 uchar pic[240*160*3*2];
20 s32int rpx0, rpy0, rpx1, rpy1, rpx, rpy;
24 u8int mosaic, mctr, lasti;
28 static bg bgst[4] = {{.n = 0}, {.n = 1}, {.n = 2}, {.n = 3}};
31 VAR(hblank), VAR(ppuy), VAR(hblclock),
32 VAR(bldy), VAR(blda), VAR(bldb), VAR(objalpha),
33 VAR(bgst[2].rpx0), VAR(bgst[2].rpy0), VAR(bgst[3].rpx0), VAR(bgst[3].rpy0),
37 typedef struct sprite sprite;
56 static sprite sprt[128], *sp = sprt;
82 #define SRCBG(n) ((n)<<17)
91 uchar ws, h, hb, d, dy, s;
92 static uchar wss[16] = {3, 4, 5, 6, 4, 5, 5, 6, 3, 3, 4, 5};
93 static uchar hss[16] = {3, 4, 5, 6, 3, 3, 4, 5, 4, 5, 5, 6};
97 budg = (cnt & HBLFREE) != 0 ? 954 : 1210;
98 for(p = oam; p < oam + 512; p += 4){
100 if((t0 & (SPRROT|SPRDIS)) == SPRDIS)
103 s = t0 >> 30 & 3 | t0 >> 12 & 12;
104 hb = h = 1 << hss[s];
105 dy = ppuy - (u8int) t0;
106 if((t0 & (SPRROT|SPRDOUB)) == (SPRROT|SPRDOUB))
108 if(dy >= hb || (u8int)t0 + hb > 256 && ppuy + 256 - (u8int)t0 >= hb)
110 if((t0 & SPRMOSA) != 0){
111 dy = dy - dy % ((reg[MOSAIC] >> 12 & 15) + 1);
114 sp->x = (s32int)(t0 << 7) >> 23;
117 sp->wb = sp->w = 1<<ws;
120 sp->base = vram + 0x10000 + ((t1 & 0x3ff) << 5);
121 d = (t0 & SPR8) != 0;
122 sp->ysh = (cnt & OBJNOMAT) != 0 ? 2 + d + ws : 10;
123 if((t0 & SPRROT) != 0){
124 if((t0 & SPRDOUB) != 0)
126 budg -= 10 + sp->w*2;
127 pp = oam + 3 + (t0 >> 21 & 0x1f0);
130 sp->rx = (dy - hb/2) * (s16int) pp[4] + (sp->w << 7) - sp->dx * sp->wb/2;
131 sp->ry = (dy - hb/2) * (s16int)pp[12] + (sp->h << 7) - sp->dy * sp->wb/2;
133 sp->rx -= sp->x * sp->dx;
134 sp->ry -= sp->x * sp->dy;
138 if((t0 & SPRVFLIP) != 0)
140 sp->base += (dy & 7) << 2 + d;
141 sp->base += dy >> 3 << sp->ysh;
142 if((t0 & SPRHFLIP) != 0)
143 sp->base += sp->w - 7 << 2 + d;
144 sp->inc = (1 << 5 + d) - (1 << 2 + d);
146 if((t0 & SPRHFLIP) != 0){
147 sp->base -= ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
148 if((t0 & SPR8) == 0 && (sp->x & 1) != 0)
151 sp->base += ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
154 sp->pal = pram + 0x100;
156 sp->pal = pram + 0x100 + (t1 >> 8 & 0xf0);
166 int x0, i, dx, sx0, sx1;
173 for(s = sprt; s < sp; s++){
174 if(s->x >= x1 || s->x + s->wb <= x0)
177 pri = s->t1 >> 10 & 3;
178 sx0 = s->x >= x0 ? s->x : x0;
183 for(i = sx0; i < sx1; i++, dx++){
184 if((t0 & SPRROT) != 0){
185 d = (t0 & SPR8) != 0;
190 if(x < s->w && y < s->h){
192 b += (y & 7) << 2 + d;
193 b += y >> 3 << s->ysh;
194 b += (x & 7) >> 1 - d;
195 b += x >> 3 << 5 + d;
204 }else if((t0 & SPRHFLIP) != 0){
207 else if((dx & 1) != 0)
217 else if((dx & 1) != 0){
225 if((t0 & SPRMOSA) != 0)
227 s->mctr = reg[MOSAIC] >> 8 & 15;
234 c = s->pal[v] | SRCOBJ;
235 switch(t0 >> 10 & 3){
246 if((reg[DISPCNT] & 1<<15) != 0)
256 bgpixel(bg *b, int i, u32int c, int pri)
265 for(j = (u8int)(b->lasti+1); j <= i; j++){
272 b->mctr = reg[MOSAIC] & 15;
275 if(b->curpri != VACANT && (pixwin[j] & 1<<b->n) == 0)
276 bgpixel(nil, j, b->curc, b->curpri);
289 }else if(pri < p[240]){
298 bginit(bg *b, int scal, int)
304 b->mosaic = (reg[BG0CNT + b->n] & BGMOSAIC) != 0;
310 rr = reg + (b->n - 2 << 3);
312 b->rpx0 = (s32int)(rr[BG2XL] | rr[BG2XH] << 16) << 4 >> 4;
313 b->rpy0 = (s32int)(rr[BG2YL] | rr[BG2YH] << 16) << 4 >> 4;
315 if(!b->mosaic || ppuy % ((reg[MOSAIC] >> 4 & 15) + 1) == 0){
321 b->rpx0 += (s16int)rr[BG2PB];
322 b->rpy0 += (s16int)rr[BG2PD];
324 rr = reg + (b->n << 1);
325 x = rr[BG0HOFS] & 0x1ff;
328 msz = (reg[MOSAIC] >> 4 & 15) + 1;
331 y += (rr[BG0VOFS] & 0x1ff);
342 switch(reg[DISPCNT] & 7){
344 bginit(&bgst[0], 0, 0);
345 bginit(&bgst[1], 0, 0);
346 bginit(&bgst[2], 0, 0);
347 bginit(&bgst[3], 0, 0);
350 bginit(&bgst[0], 0, 0);
351 bginit(&bgst[1], 0, 0);
352 bginit(&bgst[2], 1, 0);
355 bginit(&bgst[2], 1, 0);
356 bginit(&bgst[3], 1, 0);
361 bginit(&bgst[2], 1, 1);
369 u8int *base, *p, pri, d;
370 u16int cnt, *rr, sx, sy;
374 if((cnt & 1<<8 + b->n) == 0)
376 rr = reg + (b->n - 2 << 3);
387 if((cnt & FRAME) != 0 && (cnt & 7) != 3)
389 pri = reg[BG0CNT + b->n] & 3;
390 for(i = ppux0; i < x1; i++){
391 if(((pixwin[i] & 1<<b->n) == 0 || b->mosaic) && (u32int)b->rpx < sx && (u32int)b->rpy < sy){
393 p = base + 2 * (b->rpx >> 8) + 480 * (b->rpy >> 8);
394 v = p[0] | p[1] << 8;
396 v = base[(b->rpx >> 8) + 240 * (b->rpy >> 8)];
403 bgpixel(b, i, v, pri);
406 b->rpx += (s16int) rr[BG2PA];
407 b->rpy += (s16int) rr[BG2PC];
415 u16int bgcnt, ta0, ta, tx, ty, t, *pal;
419 if((reg[DISPCNT] & 1<<8 + b->n) == 0)
421 bgcnt = reg[BG0CNT + b->n];
425 ta0 = (bgcnt << 3 & 0xf800) + ((ty & 0x1f) << 6);
427 case 2: ta0 += ty << 6 & 0x800; break;
428 case 3: ta0 += ty << 7 & 0x1000; break;
432 for(; x < x1; tx++, i = 0){
433 ta = ta0 + ((tx & 0x1f) << 1);
434 if((bgcnt & 1<<14) != 0)
435 ta += tx << 6 & 0x800;
436 t = vram[ta] | vram[ta+1] << 8;
440 pal = pram + (t >> 8 & 0xf0);
441 ca = (bgcnt << 12 & 0xc000) + ((t & 0x3ff) << 5+d);
449 for(; i < 8; i++, x++){
452 if((pixwin[x] & 1<<b->n) != 0 && !b->mosaic)
464 bgpixel(b, x, pal[v], bgcnt & 3);
476 u16int bgcnt, *rr, ta;
477 int i, row, sz, x, y;
479 rr = reg + (b->n - 2 << 3);
480 if((reg[DISPCNT] & 1<<8 + b->n) == 0)
482 bgcnt = reg[BG0CNT + b->n];
483 row = (bgcnt >> 14) + 4;
485 for(i = ppux0; i < x1; i++){
488 b->rpx += (s16int) rr[BG2PA];
489 b->rpy += (s16int) rr[BG2PC];
490 if((pixwin[i] & 1<<b->n) != 0 && !b->mosaic)
492 if((bgcnt & DISPWRAP) != 0){
495 }else if((uint)x >= sz || (uint)y >= sz)
497 ta = (bgcnt << 3 & 0xf800) + ((y >> 3) << row) + (x >> 3);
498 p = vram + (bgcnt << 12 & 0xc000) + (vram[ta] << 6);
499 p += (x & 7) + ((y & 7) << 3);
501 bgpixel(b, i, pram[v], bgcnt & 3);
509 static u8int wintab[8] = {2, 3, 1, 1, 0, 0, 0, 0};
515 if((cnt >> 13) != 0){
516 if((cnt & 1<<13) != 0){
519 if(ppuy < (u8int)v && ppuy >= v >> 8){
526 for(i = sx0; i < sx1; i++)
530 if((cnt & 1<<14) != 0){
533 if(ppuy < (u8int)v && ppuy >= v >> 8){
540 for(i = sx0; i < sx1; i++)
544 for(i = ppux0; i < x1; i++){
545 v = wintab[pixwin[i]];
546 h = reg[WININ + (v & 2) / 2];
552 for(i = ppux0; i < x1; i++)
553 if(pixpri[i] == VACANT || (pixwin[i] & 1<<4) != 0){
554 pixcol[i] = pram[0] | SRCBACK;
555 pixpri[i] = BACKDROP;
557 pixcol[i+240] = pram[0] | SRCBACK;
558 pixpri[i+240] = BACKDROP;
564 mix(u16int c1, u16int c2)
566 u16int r, g, b, eva, evb;
570 b = ((c1 & 0x7c00) * eva + (c2 & 0x7c00) * evb) >> 4;
571 g = ((c1 & 0x03e0) * eva + (c2 & 0x03e0) * evb) >> 4;
572 r = ((c1 & 0x001f) * eva + (c2 & 0x001f) * evb) >> 4;
573 if(b > 0x7c00) b = 0x7c00;
574 if(g > 0x03e0) g = 0x03e0;
575 if(r > 0x001f) r = 0x001f;
576 return b & 0x7c00 | g & 0x03e0 | r;
586 b = b + (0x7c00 - b) * y / 16;
588 g = g + (0x03e0 - g) * y / 16;
590 r = r + (0x001f - r) * y / 16;
591 if(b > 0x7c00) b = 0x7c00;
592 if(g > 0x03e0) g = 0x03e0;
593 if(r > 0x001f) r = 0x001f;
594 return b & 0x7c00 | g & 0x03e0 | r;
609 return b & 0x7c00 | g & 0x03e0 | r;
619 bldcnt = reg[BLDCNT];
620 if((bldcnt & 3<<6) == 0 && objalpha == 0)
623 for(i = ppux0; i < x1; i++, p++){
624 if((*p & OBJALPHA) != 0)
626 if((pixwin[i] & 1<<5) != 0 || (bldcnt & 1<<(*p >> 17)) == 0)
628 switch(bldcnt >> 6 & 3){
631 if((bldcnt & 1<<8+(p[240] >> 17)) == 0)
633 *p = mix(*p, p[240]);
652 union { u16int w; u8int b[2]; } u;
656 q = pic + ppuy * 240 * 2 * scale;
685 if(hblank || ppuy >= 160)
692 if((cnt & FBLANK) != 0){
693 for(i = ppux0; i < x1; i++)
699 if((cnt & 1<<12) != 0)
730 extern Event evhblank;
733 stat = reg[DISPSTAT];
735 hblclock = clock + evhblank.time;
736 addevent(&evhblank, 240*4);
739 memset(pixpri, VACANT, sizeof(pixpri));
740 memset(pixwin, 0, 240);
748 }else if(ppuy == 160){
750 if((stat & IRQVBLEN) != 0)
753 if((stat & IRQVCTREN) != 0 && ppuy == stat >> 8)
759 addevent(&evhblank, 68*4);
761 if((stat & IRQHBLEN) != 0)
769 ppuwrite(u16int a, u16int v)
771 syncppu((clock - hblclock) / 4);
777 bldb = v >> 8 & 0x1f;
786 case BG2XL*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff0000 | v; break;
787 case BG2XH*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
788 case BG2YL*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff0000 | v; break;
789 case BG2YH*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;
790 case BG3XL*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff0000 | v; break;
791 case BG3XH*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
792 case BG3YL*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff0000 | v; break;
793 case BG3YH*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;