9 ulong hblclock, rendclock;
10 jmp_buf mainjmp, renderjmp;
11 static int cyc, done, ppux, ppux0;
15 Var ppuvars[] = {VAR(ppustate), VAR(ppuy), VAR(hblclock), VAR(rendclock), {nil, 0, 0}};
17 #define ryield() {if(setjmp(renderjmp) == 0) longjmp(mainjmp, 1);}
18 #define myield() {if(setjmp(mainjmp) == 0) longjmp(renderjmp, 1);}
20 typedef struct sprite sprite;
37 sprite spr[10], *sprm;
42 int x, y, i, n, m, win;
44 u8int tile, attr, pali;
46 #define eat(nc) if(cyc <= nc){for(i = 0; i < nc; i++) if(--cyc == 0) ryield();} else cyc -= nc;
53 m = 168 + (reg[SCX] & 7);
55 if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] <= 166)
58 else if(reg[WX] == 166)
61 m = reg[WX] + (reg[SCX] & 7) + 1;
66 picp = (u32int*)pic + ppuy * PICW * scale;
67 y = ppuy + reg[SCY] << 1 & 14;
68 ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | reg[SCX] >> 3;
74 attr = vram[8192 + ta];
75 if((reg[LCDC] & BGTILE) != 0)
78 ca = 0x1000 + ((s32int)(tile << 24) >> 20) + y;
79 if((attr & 0x40) != 0)
81 ca |= (attr & 8) << 10;
82 chr = vram[ca] << 8 | vram[ca+1];
83 pali = attr << 2 & 0x1c;
84 if((attr & 0x20) == 0)
85 for(i = 0; i < 8; i++){
86 sr[i] = pal[pali | chr >> 15 | chr >> 6 & 2] | ((chr & 0x8080) == 0) << prish;
90 for(i = 0; i < 8; i++){
91 sr[i] = pal[pali | chr << 1 & 2 | chr >> 8 & 1] | ((chr & 0x0101) == 0) << prish;
94 if((attr & 0x80) != 0)
95 for(i = 0; i < 8; i++)
97 if((reg[LCDC] & BGEN) == 0 && (mode & COL) == 0 && ((mode & CGB) != 0 || win == 0))
98 for(i = 0; i < 8; i++)
101 for(i = 0; i < 2*8; i++)
104 y = ppuy + reg[SCY] << 1 & 14;
105 ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | ta & 0x1f;
110 if((ta & 0x1f) == 0x1f)
114 for(i = 0; i < n; i++, x++)
121 ta = 0x1800 | reg[LCDC] << 4 & 0x400 | ppuy - reg[WY] << 2 & 0x3e0;
122 y = ppuy - reg[WY] << 1 & 14;
142 sy = (reg[LCDC] & SPR16) != 0 ? 16 : 8;
144 if((reg[LCDC] & SPREN) == 0)
146 for(p = oam; p < oam + 160; p += 4){
147 if((u8int)(y0 - p[0]) >= sy)
149 if((mode & COL) == 0){
150 for(q = spr; q < sprm; q++)
152 if(sprm != spr + 10){
153 memmove(q + 1, q, (sprm - q) * sizeof(sprite));
156 memmove(q + 1, q, (sprm - 1 - q) * sizeof(sprite));
168 if((t & SPRYFL) != 0)
172 tn = tn & ~1 | q->dy >> 3;
173 chrp = vram + (tn << 4 | q->dy << 1 & 14);
174 if((mode & COL) != 0){
175 chrp += t << 10 & 0x2000;
176 q->pal = 0x20 | t << 2 & 0x1c;
178 q->pal = 4 + (t >> 2 & 4);
179 q->chr = chrp[0] << 8 | chrp[1];
181 if((t & SPRXFL) != 0)
186 if((mode & COL) != 0 && sprm == spr + 10)
200 picp = (u32int*)pic + ppuy * PICW * scale;
201 for(q = spr; q < sprm; q++){
202 if(q->x <= ppux0 || q->x >= ppux + 8)
205 if(x < ppux0) x = ppux0;
207 if(x1 > ppux) x1 = ppux;
209 attr = picp[x] >> prish;
211 if((chr & ((q->t & SPRXFL) != 0 ? 0x0101 : 0x8080)) != 0 && (attr & TILSPR) == 0 &&
212 ((mode & COL) != 0 && (reg[LCDC] & BGPRI) == 0 ||
213 (attr & TILCOL0) != 0 ||
214 (attr & TILPRI) == 0 && (q->t & SPRPRI) == 0))
215 if((q->t & SPRXFL) == 0)
216 picp[x] = pal[q->pal | chr >> 15 | chr >> 6 & 2] | TILSPR << prish;
218 picp[x] = pal[q->pal | chr << 1 & 2 | chr >> 8 & 1] | TILSPR << prish;
219 if((q->t & SPRXFL) != 0)
233 cyc = clock - rendclock;
245 t = 174 + (reg[SCX] & 7);
246 if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] < 166)
257 u32int *picp, *p, *q, l;
260 picp = (u32int*)pic + ppuy * PICW * scale;
262 q = picp + PICW * scale;
263 for(i = PICW; --i >= 0; ){
289 extern Event evhblank;
294 hblclock = clock + evhblank.time;
297 if((reg[STAT] & IRQM1) != 0)
299 addevent(&evhblank, 456*2);
304 if((reg[STAT] & IRQM2) != 0)
306 addevent(&evhblank, 80*2);
308 if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
312 hblclock = clock + evhblank.time;
316 if((reg[STAT] & IRQM2) != 0)
318 addevent(&evhblank, 80*2);
320 addevent(&evhblank, 456*2);
321 if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
326 rendclock = clock + evhblank.time;
328 addevent(&evhblank, linelen());
332 if(!done) print("not done?!\n");
337 if((reg[STAT] & IRQM0) != 0)
339 t = hblclock + 456 * 2 - clock;
340 addevent(&evhblank, t < 0 ? 456 * 2 : t);
350 static char ppustack[4096];
352 renderjmp[JMPBUFPC] = (uintptr)ppurender;
353 renderjmp[JMPBUFSP] = (uintptr)(ppustack + sizeof(ppustack) - 64);