shithub: fork

Download patch

ref: 8ec800d6991218c256de524b1132478533bee574
parent: 2b1975d6a669372c7d734213996d5123ee1c378f
author: qwx <qwx@sciops.net>
date: Tue Aug 5 06:02:58 EDT 2025

games/*: eui scaling patch applied

--- a/sys/src/games/2600/tia.c
+++ /dev/null
@@ -1,195 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppux=1, ppuy;
-int col, pri;
-u8int p0x, p1x, m0x, m1x, blx;
-u16int coll;
-u8int disp;
-int p0difc;
-int bwmod = 1<<3;
-
-enum {
-	SRCPF,
-	SRCP0,
-	SRCP1,
-	SRCM0,
-	SRCM1,
-	SRCBL,
-};
-
-static void
-pixeldraw(u8int v)
-{
-	u32int c;
-	union { u32int l; u8int c[4]; } u;
-	u32int *p;
-	static u32int col[] = {
-		0x000000, 0x404040, 0x6C6C6C, 0x909090, 0xB0B0B0, 0xC8C8C8, 0xDCDCDC, 0xECECEC, 
-		0x444400, 0x646410, 0x848424, 0xA0A034, 0xB8B840, 0xD0D050, 0xE8E85C, 0xFCFC68, 
-		0x702800, 0x844414, 0x985C28, 0xAC783C, 0xBC8C4C, 0xCCA05C, 0xDCB468, 0xECC878, 
-		0x841800, 0x983418, 0xAC5030, 0xC06848, 0xD0805C, 0xE09470, 0xECA880, 0xFCBC94, 
-		0x880000, 0x9C2020, 0xB03C3C, 0xC05858, 0xD07070, 0xE08888, 0xECA0A0, 0xFCB4B4, 
-		0x78005C, 0x8C2074, 0xA03C88, 0xB0589C, 0xC070B0, 0xD084C0, 0xDC9CD0, 0xECB0E0, 
-		0x480078, 0x602090, 0x783CA4, 0x8C58B8, 0xA070CC, 0xB484DC, 0xC49CEC, 0xD4B0FC, 
-		0x140084, 0x302098, 0x4C3CAC, 0x6858C0, 0x7C70D0, 0x9488E0, 0xA8A0EC, 0xBCB4FC, 
-		0x000088, 0x1C209C, 0x3840B0, 0x505CC0, 0x6874D0, 0x7C8CE0, 0x90A4EC, 0xA4B8FC, 
-		0x00187C, 0x1C3890, 0x3854A8, 0x5070BC, 0x6888CC, 0x7C9CDC, 0x90B4EC, 0xA4C8FC, 
-		0x002C5C, 0x1C4C78, 0x386890, 0x5084AC, 0x689CC0, 0x7CB4D4, 0x90CCE8, 0xA4E0FC, 
-		0x003C2C, 0x1C5C48, 0x387C64, 0x509C80, 0x68B494, 0x7CD0AC, 0x90E4C0, 0xA4FCD4, 
-		0x003C00, 0x205C20, 0x407C40, 0x5C9C5C, 0x74B474, 0x8CD08C, 0xA4E4A4, 0xB8FCB8, 
-		0x143800, 0x345C1C, 0x507C38, 0x6C9850, 0x84B468, 0x9CCC7C, 0xB4E490, 0xC8FCA4, 
-		0x2C3000, 0x4C501C, 0x687034, 0x848C4C, 0x9CA864, 0xB4C078, 0xCCD488, 0xE0EC9C, 
-		0x442800, 0x644818, 0x846830, 0xA08444, 0xB89C58, 0xD0B46C, 0xE8CC7C, 0xFCE08C, 
-	};
-	
-	c = col[v >> 1];
-	u.c[0] = c;
-	u.c[1] = c >> 8;
-	u.c[2] = c >> 16;
-	u.c[3] = 0xff;
-	p = (u32int *)pic + ppuy * PICW + ppux * 2;
-	p[0] = p[1] = u.l;
-}
-
-static void
-pixel(u8int v, int p, int s)
-{
-	if(p > pri){
-		col = v;
-		pri = p;
-	}
-	disp |= 1<<s;
-}
-
-static void
-playfield(void)
-{
-	int x, p;
-	u8int c;
-	
-	x = ppux / 4;
-	if(x >= 20)
-		if((reg[CTRLPF] & 1) != 0)
-			x = 39 - x;
-		else
-			x = x - 20;
-	if(x < 4){
-		if((reg[PF0] & 0x10<<x) == 0)
-			return;
-	}else if(x < 12){
-		if((reg[PF1] & 0x800>>x) == 0)
-			return;
-	}else
-		if((reg[PF2] & 1<<x-12) == 0)
-			return;
-	if((reg[CTRLPF] & 6) == 2)
-		if(ppux < 80){
-			c = reg[COLUP0];
-			p = 3;
-		}else{
-			c = reg[COLUP1];
-			p = 2;
-		}
-	else{
-		c = reg[COLUPF];
-		p = (reg[CTRLPF] & 4) + 1;
-	}
-	pixel(c, p, SRCPF);
-}
-
-static void
-player(int n)
-{
-	u8int c;
-	int x;
-
-	c = reg[GRP0 + n];
-	x = ppux - (n ? p1x : p0x);
-	if(x < 0)
-		return;
-	switch(reg[NUSIZ0 + n] & 7){
-	default: if(x >= 8) return; break;
-	case 1: if(x >= 8 && (x < 16 || x >= 24)) return; break;
-	case 2: if(x >= 8 && (x < 32 || x >= 40)) return; break;
-	case 3: if(x >= 40 || ((x & 15) >= 8)) return; break;
-	case 4: if(x >= 8 && (x < 64 || x >= 72)) return; break;
-	case 5: if(x >= 16) return; x >>= 1; break;
-	case 6: if(x >= 72 || ((x & 31) >= 8)) return; break;
-	case 7: if(x >= 32) return; x >>= 2; break;
-	}
-	x &= 7;
-	if((reg[REFP0 + n] & 8) == 0)
-		x ^= 7;
-	if((c & 1<<x) == 0)
-		return;
-	c = reg[COLUP0 + n];
-	pixel(c, 3 - n, SRCP0 + n);
-}
-
-static void
-missile(int n)
-{
-	int x;
-
-	x = ppux - (n ? m1x : m0x);
-	if((reg[RESMP0 + n] & 2) != 0){
-		if(n)
-			m1x = p1x;
-		else
-			m0x = p0x;
-		return;
-	}
-	if(x < 0 || x >= 1<<(reg[NUSIZ0] >> 4 & 3) || (reg[ENAM0 + n] & 2) == 0)
-		return;
-	pixel(reg[COLUP0 + n], 3 - n, SRCM0 + n);
-}
-
-static void
-ball(void)
-{
-	int x;
-
-	x = ppux - blx;
-	if(x < 0 || x >= 1<<(reg[CTRLPF] >> 4 & 3) || (reg[ENABL] & 2) == 0)
-		return;
-	pixel(reg[COLUPF], (reg[CTRLPF] & 4) + 1, SRCBL);
-}
-
-void
-tiastep(void)
-{
-	static u16int colltab[64] = {
-		0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0080, 0x8000, 0x80a0,
-		0x0000, 0x0200, 0x0001, 0x0221, 0x0002, 0x0282, 0x8003, 0x82a3,
-		0x0000, 0x0800, 0x0008, 0x0828, 0x0004, 0x0884, 0x800c, 0x88ac,
-		0x4000, 0x4a00, 0x4009, 0x4a29, 0x4006, 0x4a86, 0xc00f, 0xcaaf,
-		0x0000, 0x2000, 0x0010, 0x2030, 0x0040, 0x20c0, 0x8050, 0xa0f0,
-		0x0100, 0x2300, 0x0111, 0x2331, 0x0142, 0x23c2, 0x8153, 0xa3f3,
-		0x0400, 0x2c00, 0x0418, 0x2c38, 0x0444, 0x2cc4, 0x845c, 0xacfc,
-		0x4500, 0x6f00, 0x4519, 0x6f39, 0x4546, 0x6fc6, 0xc55f, 0xefff,
-	};
-
-	if(ppuy < PICH && ppux < 160){
-		col = reg[COLUBK];
-		pri = 0;
-		disp = 0;
-		playfield();
-		player(0);
-		player(1);
-		missile(0);
-		missile(1);
-		ball();
-		coll |= colltab[disp];
-		pixeldraw(col);
-	}
-	if(ppux == 160)
-		nrdy = 0;
-	if(++ppux == 228){
-		ppuy++;
-		ppux = 0;
-	}
-}
--- a/sys/src/games/c64/vic.c
+++ /dev/null
@@ -1,369 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int region, picidx;
-u16int ppux, ppuy, lastx, wrapx, maxy, lvis, rvis, uvis, dvis, picw, pich, lbord, rbord, ubord, dbord, spr0;
-u16int vc, vcbase, vmli;
-u8int badln, rc, displ, fract, visreg, hbord, vbord, rbord0, lbord0;
-u16int chrp[40];
-u64int pxs, npxs, npxs0, opxs;
-u8int fg;
-
-typedef struct spr spr;
-enum {
-	SPRFDMA = 1,
-	SPRFYEX = 2,
-	SPRFDISP = 4,
-};
-struct spr {
-	u8int flags;
-	u32int data;
-	u8int mc, mcbase, dp;
-	u16int x;
-} sp[8];
-
-void
-bordset(void)
-{
-	int r, c;
-
-	r = (reg[CTRL1] & RSEL) != 0;
-	c = (reg[CTRL2] & CSEL) != 0;
-	lbord = c ? 0x14 : 0x1c;
-	lbord0 = c ? 0xf0 : 0xe0;
-	rbord = c ? 0x154 : 0x14c;
-	rbord0 = c ? 0x0f : 0x3f;
-	ubord = r ? 0x33 : 0x37;
-	dbord = r ? 0xfb : 0xf7;
-	if((reg[CTRL1] & DEN) == 0)
-		ubord = -1;
-}
-
-void
-vicreset(void)
-{
-	switch(region){
-	case NTSC0:
-		lastx = 0x1fc;
-		wrapx = 0x19c;
-		maxy = 262;
-		picw = 412;
-		pich = 234;
-		spr0 = 0x16c;
-		lvis = 0x1e4;
-		rvis = 0x184;
-		uvis = 41;
-		dvis = 13;
-		break;
-	case NTSC:
-		lastx = 0x1fc;
-		wrapx = 0x19c;
-		maxy = 263;
-		picw = 419;
-		pich = 235;
-		spr0 = 0x174;
-		lvis = 0x1e4;
-		rvis = 0x18c;
-		uvis = 41;
-		dvis = 13;
-		break;
-	case PAL:
-		lastx = 0x1f4;
-		wrapx = 0x194;
-		maxy = 312;
-		picw = 404;
-		pich = 284;
-		spr0 = 0x164;
-		lvis = 0x1dc;
-		rvis = 0x17c;
-		uvis = 16;
-		dvis = 300;
-		break;
-	}
-	ppux = 4;
-	ppuy = 0;
-	bordset();
-}
-
-void
-pixeldraw(u64int p, int n)
-{
-	int i;
-	union { u8int c[4]; u32int l; } u;
-	static u8int cr[] = {0, 255, 136, 170, 204, 0, 0, 238, 221, 102, 255, 51, 119, 170, 0, 187};
-	static u8int cg[] = {0, 255, 0, 255, 68, 204, 0, 238, 136, 68, 119, 51, 119, 255, 136, 187};
-	static u8int cb[] = {0, 255, 0, 238, 204, 85, 170, 119, 85, 0, 119, 51, 119, 102, 255, 187};
-	u8int c;
-	u32int *q;
-
-	q = (u32int *)pic + picidx;
-	for(i = 0; i < n; i++){
-		c = p >> 56;
-		p <<= 8;
-		u.c[0] = cb[c];
-		u.c[1] = cg[c];
-		u.c[2] = cr[c];
-		u.c[3] = 0;
-		*q++ = u.l;
-	}
-	picidx += n;
-}
-
-void
-pixels(u8int d, u16int c)
-{
-	u8int c0, c1, c2, n;
-	int i;
-
-	npxs0 = npxs;
-	npxs = 0;
-	switch((reg[CTRL1] & (ECM|BMM) | reg[CTRL2] & MCM) >> 4){
-	case 0:
-		c0 = c >> 8;
-	normal:
-		fg = d;
-		for(i = 0; i < 8; i++){
-			npxs = npxs << 8 | ((d & 0x80) != 0 ? c0 : reg[BG0]);
-			d <<= 1;
-		}
-		break;
-	case 1:
-		c0 = c >> 8 & 7;
-		if((c & 0x800) == 0)
-			goto normal;
-		fg = d & 0xaa | d >> 1 & 0x55;
-		for(i = 0; i < 8; i += 2){
-			n = d >> 6;
-			npxs = npxs << 16 | (n == 3 ? c0 : reg[BG0 + n]) * 0x101;
-			d <<= 2;
-		}
-		break;
-	case 2:
-		c0 = c & 15;
-		c1 = c >> 4 & 15;
-		fg = d;
-		for(i = 0; i < 8; i++){
-			npxs = npxs << 8 | ((d & 0x80) != 0 ? c1 : c0);
-			d <<= 1;
-		}
-		break;
-	case 3:
-		c0 = c & 15;
-		c1 = c >> 4 & 15;
-		c2 = c >> 8;
-		fg = d & 0xaa | d >> 1 & 0x55;
-		for(i = 0; i < 8; i += 2){
-			n = d >> 6;
-			switch(n){
-			default: n = reg[BG0]; break;
-			case 1: n = c1; break;
-			case 2: n = c0; break;
-			case 3: n = c2;
-			}
-			npxs = npxs << 16 | n * 0x101;
-			d <<= 2;
-		}
-		break;
-	case 4:
-		c0 = c >> 8;
-		fg = d;
-		for(i = 0; i < 8; i++){
-			npxs = npxs << 8 | ((d & 0x80) != 0 ? c0 : reg[BG0 + (d >> 6 & 3)]);
-			d <<= 1;
-		}
-		break;
-	default:
-		fg = 0;
-		break;
-	}
-}
-
-void
-bgpixels(void)
-{
-	int i, j, x;
-	u8int h;
-	u8int spract, s, o;
-	
-	h = hbord;
-	opxs = 0;
-	for(i = 0; i < 8; i++){
-		if((reg[CTRL2] + 4 & 7) == i)
-			pxs = i >= 4 ? npxs : npxs0;
-		o = pxs >> 56;
-		pxs <<= 8;
-
-		x = ppux + i;
-		spract = 0;
-		for(j = 0; j < 8; j++)
-			if((sp[j].flags & SPRFDISP) != 0 && (u16int)(x-sp[j].x) < 48 && (sp[j].data & ((reg[SPRMC]&1<<j)?3:2)<<22) != 0)
-				spract |= 1<<j;
-		if((spract & spract - 1) != 0 && vbord == 0){
-			reg[SPRSPR] |= spract;
-			irq |= IRQSPRCOLL;
-		}
-		if(fg != 0 && spract != 0 && vbord == 0){
-			reg[SPRBG] |= spract;
-			irq |= IRQBGCOLL;
-		}
-		s = spract & ~(reg[SPRDP] & ((s8int)fg) >> 7);
-		if(s != 0)
-			for(j = 0; j < 8; j++)
-				if((s & 1<<j) != 0){
-					if((reg[SPRMC] & 1<<j) != 0)
-						switch(sp[j].data >> 22 & 3){
-						case 1: o = reg[SPRMC0]; break;
-						case 2: o = reg[SPRCOL+j]; break;
-						case 3: o = reg[SPRMC1]; break;
-						}
-					else
-						o = reg[SPRCOL+j];
-					break;
-				}
-		if((h & 0x80) != 0)
-			o = reg[EC];
-		opxs = opxs << 8 | o;
-		h <<= 1;
-		fg <<= 1;
-		for(j = 0; j < 8; j++)
-			if((u16int)(x-sp[j].x) < 48 && ((reg[SPRXE] & 1<<j) == 0 || (x-sp[j].x & 1) != 0))
-				if((reg[SPRMC] & 1<<j) != 0){
-					if((x-sp[j].x & 1) != 0)
-						sp[j].data <<= 2;
-				}else
-					sp[j].data <<= 1;
-	}
-}
-
-void
-vicstep(void)
-{
-	u16int gaddr;
-	int i;
-
-	if(ppuy == 0x30 && (reg[CTRL1] & DEN) != 0)
-		fract = 1;
-	badln = ((ppuy ^ reg[CTRL1]) & 7) == 0 && fract;
-	hbord = ((s8int)(hbord << 7)) >> 7;
-	if(ppux == rbord && hbord == 0)
-		hbord = rbord0;
-	else if(ppux == lbord){
-		if(ppuy == dbord)
-			vbord = 1;
-		if(ppuy == ubord)
-			vbord = 0;
-		if(!vbord)
-			hbord = lbord0;
-	}
-	if(badln)
-		displ = 1;
-	if(ppux == 4){
-		vc = vcbase;
-		vmli = 0;
-		if(badln)
-			rc = 0;
-	}
-	if(ppux == 12)
-		for(i = 0; i < 8; i++){
-			if((sp[i].flags & SPRFDISP) == 0 || (reg[SPRYE] & 1<<i) != 0 && (sp[i].flags & SPRFYEX) == 0)
-				continue;
-			sp[i].mcbase += 3;
-			if(sp[i].mcbase == 63)
-				sp[i].flags &= ~(SPRFDMA|SPRFDISP);
-		}
-	if(ppux >= 0x14 && ppux <= 0x14c){
-		if((reg[CTRL1] & BMM) != 0)
-			gaddr = (reg[MEMP] & 0x08) << 10 | vc << 3 | rc;
-		else
-			gaddr = (reg[MEMP] & 0x0e) << 10 | (chrp[vmli] & 0xff) << 3 | rc;
-		if(!displ)
-			gaddr = 0x3fff;
-		if((reg[CTRL1] & ECM) != 0)
-			gaddr &= ~0x600;
-		pixels(vmemread(gaddr) & -displ, chrp[vmli] & -displ);
-		vmli++;
-		vc = vc + 1 & 0x3ff;
-	}
-	if(visreg && (ppux >= lvis || ppux < rvis)){
-		bgpixels();
-		pixeldraw(opxs, ppux == lvis ? region == NTSC ? 3 : 4 : 8);
-	}
-	if(ppux == 0x14c){
-		for(i = 0; i < 8; i++){
-			if((reg[SPRYE] & 1<<i) != 0)
-				sp[i].flags ^= SPRFYEX;
-			if((reg[SPREN] & 1<<i) == 0 || reg[2*i+1] != (u8int)ppuy)
-				continue;
-			sp[i].flags |= SPRFDMA;
-			sp[i].mcbase = 0;
-			if((reg[SPRYE] & 1<<i) != 0)
-				sp[i].flags &= ~SPRFYEX;		
-		}
-	}else if(ppux == 0x154)
-		npxs = reg[BG0] * 0x0101010101010101ULL;
-	if(badln){
-		if(ppux == lastx - 8)
-			nrdy = 1;
-		else if(ppux >= 0xc && ppux <= 0x144)
-			chrp[vmli] = vmemread(vc | (reg[MEMP] & 0xf0) << 6) | cram[vc] << 8;
-		else if(ppux == 0x154)
-			nrdy = 0;
-	}
-	if(ppux == 0x164){
-		if(displ && rc == 7){
-			displ = badln;
-			vcbase = vc;
-		}
-		if(displ)
-			rc = rc + 1 & 7;
-		for(i = 0; i < 8; i++){
-			sp[i].mc = sp[i].mcbase;
-			if((sp[i].flags & SPRFDMA) != 0 && reg[2*i+1] == (u8int)ppuy)
-				sp[i].flags |= SPRFDISP;
-		}
-	}
-	if((u16int)(ppux - spr0) < 128){
-		i = ppux - spr0 >> 4;
-		nrdy = (sp[i].flags & SPRFDMA) != 0;
-		if((ppux & 8) == 0){
-			sp[i].dp = vmemread((reg[MEMP] & 0xf0) << 6 | 0x3f8 | i);
-			sp[i].x = nrdy ? reg[2 * i] | reg[MSBX] << 8 - i & 0x100 : -1;
-			if(nrdy)
-				sp[i].data = vmemread(sp[i].dp << 6 | sp[i].mc++) << 16;
-		}else if(nrdy){
-			sp[i].data = sp[i].data & 0xff00ff | vmemread(sp[i].dp << 6 | sp[i].mc++) << 8;
-			sp[i].data = sp[i].data & 0xffff00 | vmemread(sp[i].dp << 6 | sp[i].mc++);
-		}
-	}else if(ppux - spr0 == 128)
-		nrdy = 0;
-	if(ppux == wrapx){
-		ppuy++;
-		if(ppuy == maxy){
-			flush();
-			ppuy = 0;
-			vcbase = 0;
-		}
-		if((ppuy & 0xff) == reg[RASTER] && ((ppuy ^ reg[CTRL1] << 1) & 0x100) == 0)
-			irq |= IRQRASTER;
-		if(ppuy == dbord)
-			vbord = 1;
-		else if(ppuy == ubord)
-			vbord = 0;
-		else if(ppuy == dvis)
-			visreg = 0;
-		if(ppuy == uvis){
-			picidx = 0;
-			visreg = 1;
-		}
-		if(ppuy == 0xf7)
-			fract = 0;
-	}
-	if(ppux == lastx)
-		ppux = 4;
-	else
-		ppux += 8;
-}
--- a/sys/src/games/eui.h
+++ /dev/null
@@ -1,19 +1,0 @@
-enum{
-	MILLION = 1000000,
-	BILLION = 1000000000,
-};
-
-extern u64int keys, keys2;
-extern int trace, paused;
-extern int savereq, loadreq;
-extern QLock pauselock;
-extern int scale, fixscale, warp10;
-extern uchar *pic;
-
-void*	emalloc(ulong);
-void	flushmouse(int);
-void	flushscreen(void);
-void	flushaudio(int(*)(void));
-void	regkeyfn(Rune, void(*)(void));
-void	regkey(char*, Rune, int);
-void	initemu(int, int, int, ulong, int, void(*)(void*));
--- a/sys/src/games/gb/ppu.c
+++ /dev/null
@@ -1,326 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-u8int ppustate, ppuy, ppuw;
-ulong hblclock, rendclock;
-jmp_buf mainjmp, renderjmp;
-static int cyc, done, ppux, ppux0;
-extern int prish;
-extern u32int white;
-
-Var ppuvars[] = {VAR(ppustate), VAR(ppuy), VAR(hblclock), VAR(rendclock), {nil, 0, 0}};
-
-#define ryield() {if(setjmp(renderjmp) == 0) longjmp(mainjmp, 1);}
-#define myield() {if(setjmp(mainjmp) == 0) longjmp(renderjmp, 1);}
-
-typedef struct sprite sprite;
-struct sprite {
-	u8int dy, x, t;
-	u8int fetched, pal;
-	u16int chr;
-};
-enum {
-	SPRPRI = 0x80,
-	SPRYFL = 0x40,
-	SPRXFL = 0x20,
-	SPRPAL = 0x10,
-	SPRBANK = 0x08,
-	
-	TILCOL0 = 0x01,
-	TILPRI = 0x02,
-	TILSPR = 0x04,
-};
-sprite spr[10], *sprm;
-
-void
-ppurender(void)
-{
-	int x, y, i, n, m, win;
-	u16int ta, ca, chr;
-	u8int tile, attr, pali;
-	u32int sr[8], *picp;
-	#define eat(nc) if(cyc <= nc){for(i = 0; i < nc; i++) if(--cyc == 0) ryield();} else cyc -= nc;
-	
-	ryield();
-	
-	attr = 0;
-	for(;;){
-		eat(6*2);
-		m = 168 + (reg[SCX] & 7);
-		win = 0;
-		if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] <= 166)
-			if(reg[WX] == 0)
-				m = 7;
-			else if(reg[WX] == 166)
-				m = 0;
-			else{
-				m = reg[WX] + (reg[SCX] & 7) + 1;
-				win = -1;
-			}
-		ppux = 0;
-		ppux0 = 0;
-		picp = (u32int*)pic + ppuy * PICW;
-		y = ppuy + reg[SCY] << 1 & 14;
-		ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | reg[SCX] >> 3;
-		x = -(reg[SCX] & 7);
-	restart:
-		do{
-			tile = vram[ta];
-			if((mode & COL) != 0)
-				attr = vram[8192 + ta];
-			if((reg[LCDC] & BGTILE) != 0)
-				ca = (tile << 4) + y;
-			else
-				ca = 0x1000 + ((s32int)(tile << 24) >> 20) + y;
-			if((attr & 0x40) != 0)
-				ca ^= 14;
-			ca |= (attr & 8) << 10;
-			chr = vram[ca] << 8 | vram[ca+1];
-			pali = attr << 2 & 0x1c;
-			if((attr & 0x20) == 0)
-				for(i = 0; i < 8; i++){
-					sr[i] = pal[pali | chr >> 15 | chr >> 6 & 2] | ((chr & 0x8080) == 0) << prish;
-					chr <<= 1;
-				}
-			else
-				for(i = 0; i < 8; i++){
-					sr[i] = pal[pali | chr << 1 & 2 | chr >> 8 & 1] | ((chr & 0x0101) == 0) << prish;
-					chr >>= 1;
-				}
-			if((attr & 0x80) != 0)
-				for(i = 0; i < 8; i++)
-					sr[i] |= 2 << prish;
-			if((reg[LCDC] & BGEN) == 0 && (mode & COL) == 0 && ((mode & CGB) != 0 || win == 0))
-				for(i = 0; i < 8; i++)
-					sr[i] = white;
-			if(cyc <= 2*8){
-				for(i = 0; i < 2*8; i++)
-					if(--cyc == 0)
-						ryield();
-				y = ppuy + reg[SCY] << 1 & 14;
-				ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | ta & 0x1f;
-			}else
-				cyc -= 2*8;
-			m -= 8;
-			n = m < 8 ? m : 8;
-			if((ta & 0x1f) == 0x1f)
-				ta &= ~0x1f;
-			else
-				ta++;
-			for(i = 0; i < n; i++, x++)
-				if(x >= 0)
-					picp[x] = sr[i];
-			ppux = x;
-		}while(m > 8);
-		if(win == -1){
-			win = 1;
-			ta = 0x1800 | reg[LCDC] << 4 & 0x400 | ppuw - reg[WY] << 2 & 0x3e0;
-			y = ppuw - reg[WY] << 1 & 14;
-			cyc += 2;
-			m = 175 - reg[WX];
-			goto restart;
-		}
-		done = 1;
-		ryield();
-	}
-}
-
-void
-oamsearch(void)
-{
-	u8int *p;
-	sprite *q;
-	int y0, sy;
-	u8int t, tn;
-	u8int *chrp;
-	
-	y0 = ppuy + 16;
-	sy = (reg[LCDC] & SPR16) != 0 ? 16 : 8;
-	sprm = spr;
-	if((reg[LCDC] & SPREN) == 0)
-		return;
-	for(p = oam; p < oam + 160; p += 4){
-		if((u8int)(y0 - p[0]) >= sy)
-			continue;
-		if((mode & COL) == 0){
-			for(q = spr; q < sprm; q++)
-				if(q->x > p[1]){
-					if(sprm != spr + 10){
-						memmove(q + 1, q, (sprm - q) * sizeof(sprite));
-						sprm++;
-					}else
-						memmove(q + 1, q, (sprm - 1 - q) * sizeof(sprite));
-					goto found;
-				}
-			if(q == spr + 10)
-				continue;
-			sprm++;
-		found:;
-		}else
-			q = sprm++;
-		q->dy = y0 - p[0];
-		q->x = p[1];
-		q->t = t = p[3];
-		if((t & SPRYFL) != 0)
-			q->dy ^= sy - 1;
-		tn = p[2];
-		if(sy == 16)
-			tn = tn & ~1 | q->dy >> 3;
-		chrp = vram + (tn << 4 | q->dy << 1 & 14);
-		if((mode & COL) != 0){
-			chrp += t << 10 & 0x2000;
-			q->pal = 0x20 | t << 2 & 0x1c;
-		}else
-			q->pal = 4 + (t >> 2 & 4);
-		q->chr = chrp[0] << 8 | chrp[1];
-		if(p[1] < 8)
-			if((t & SPRXFL) != 0)
-				q->chr >>= 8 - p[1];
-			else
-				q->chr <<= 8 - p[1];
-		q->fetched = 0;
-		if((mode & COL) != 0 && sprm == spr + 10)
-			break;
-	}
-}
-
-void
-sprites(void)
-{
-	sprite *q;
-	u8int attr;
-	u32int *picp;
-	int x, x1;
-	u16int chr;
-	
-	picp = (u32int*)pic + ppuy * PICW;
-	for(q = spr; q < sprm; q++){
-		if(q->x <= ppux0 || q->x >= ppux + 8)
-			continue;
-		x = q->x - 8;
-		if(x < ppux0) x = ppux0;
-		x1 = q->x;
-		if(x1 > ppux) x1 = ppux;
-		for(; x < x1; x++){
-			attr = picp[x] >> prish;
-			chr = q->chr;
-			if((chr & ((q->t & SPRXFL) != 0 ? 0x0101 : 0x8080)) != 0 && (attr & TILSPR) == 0 &&
-					((mode & COL) != 0 && (reg[LCDC] & BGPRI) == 0 ||
-					(attr & TILCOL0) != 0 ||
-					(attr & TILPRI) == 0 && (q->t & SPRPRI) == 0))
-				if((q->t & SPRXFL) == 0)
-					picp[x] = pal[q->pal | chr >> 15 | chr >> 6 & 2] | TILSPR << prish;
-				else
-					picp[x] = pal[q->pal | chr << 1 & 2 | chr >> 8 & 1] | TILSPR << prish;
-			if((q->t & SPRXFL) != 0)
-				q->chr >>= 1;
-			else
-				q->chr <<= 1;
-		}
-	}
-	ppux0 = ppux;
-}
-
-void
-ppusync(void)
-{
-	if(ppustate != 3)
-		return;
-	cyc = clock - rendclock;
-	if(cyc != 0)
-		myield();
-	sprites();
-	rendclock = clock;
-}
-
-int
-linelen(void)
-{
-	int t;
-	
-	t = 174 + (reg[SCX] & 7);
-	if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] < 166)
-		if(reg[WX] == 0)
-			t += 7;
-		else
-			t += 6;
-	return t*2;
-}
-
-void
-hblanktick(void *)
-{
-	extern Event evhblank;
-	int t;
-	
-	switch(ppustate){
-	case 0:
-		hblclock = clock + evhblank.time;
-		if(reg[WX] <= 166 && reg[WY] <= 143)
-			ppuw++;
-		if(++ppuy == 144){
-			ppustate = 1;
-			if((reg[STAT] & IRQM1) != 0)
-				reg[IF] |= IRQLCDS;
-			addevent(&evhblank, 456*2);
-			reg[IF] |= IRQVBL;
-			flush();
-		}else{
-			ppustate = 2;
-			if((reg[STAT] & IRQM2) != 0)
-				reg[IF] |= IRQLCDS;
-			addevent(&evhblank, 80*2);
-		}
-		if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
-			reg[IF] |= IRQLCDS;
-		break;
-	case 1:
-		hblclock = clock + evhblank.time;
-		if(reg[WX] <= 166 && reg[WY] <= 143)
-			ppuw++;
-		if(++ppuy == 154){
-			ppuy = 0;
-			ppuw = 0;
-			ppustate = 2;
-			if((reg[STAT] & IRQM2) != 0)
-				reg[IF] |= IRQLCDS;
-			addevent(&evhblank, 80*2);
-		}else
-			addevent(&evhblank, 456*2);
-		if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
-			reg[IF] |= IRQLCDS;
-		break;
-	case 2:
-		oamsearch();
-		rendclock = clock + evhblank.time;
-		ppustate = 3;
-		addevent(&evhblank, linelen());
-		break;
-	case 3:
-		ppusync();
-		if(!done) print("not done?!\n");
-		done = 0;
-		ppustate = 0;
-		if((reg[STAT] & IRQM0) != 0)
-			reg[IF] |= IRQLCDS;
-		t = hblclock + 456 * 2 - clock;
-		addevent(&evhblank, t < 0 ? 456 * 2 : t);
-		if(dma & DMAHBLANK)
-			dma |= DMAREADY;
-		break;
-	}
-}
-
-void
-ppuinit(void)
-{
-	static char ppustack[4096];
-	
-	renderjmp[JMPBUFPC] = (uintptr)ppurender;
-	renderjmp[JMPBUFSP] = (uintptr)(ppustack + sizeof(ppustack) - 64);
-	myield();
-}
--- a/sys/src/games/gba/apu.c
+++ /dev/null
@@ -1,390 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-Event evsamp;
-int srate, sratediv;
-s16int sbuf[2*4000], *sbufp, bias;
-enum {
-	Freq = 44100,
-};
-static int stime;
-s8int snddma[2];
-static int fd;
-
-u16int envctr, envrel, envmod;
-u8int sweepen, sweepctr;
-u16int sweepfreq;
-typedef struct chan chan;
-struct chan {
-	u8int n, ectr;
-	u16int len;
-	u16int *env, *freq;
-	u16int fctr, fthr;
-	u32int finc;
-	u8int vol;
-};
-u8int wave[64], wpos, wbank;
-u16int lfsr;
-
-chan sndch[4] = {
-	{
-		.n = 0,
-		.env = reg + 0x62/2,
-		.freq = reg + 0x64/2,
-	},
-	{
-		.n = 1,
-		.env = reg + 0x68/2,
-		.freq = reg + 0x6c/2,
-	},
-	{
-		.n = 2,
-	},
-	{
-		.n = 3,
-		.env = reg + 0x78/2,
-		.freq = reg + 0x7c/2,
-	}
-};
-
-Var apuvars[] = {
-	ARR(snddma), VAR(envctr), VAR(envrel), VAR(envmod), VAR(sweepen),
-	VAR(sweepctr), VAR(sweepfreq), ARR(wave), VAR(wpos), VAR(wbank), VAR(lfsr),
-	VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
-	VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
-	VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
-	VAR(sndch[3].ectr), VAR(sndch[3].len), VAR(sndch[3].fctr), VAR(sndch[3].fthr), VAR(sndch[3].finc), VAR(sndch[3].vol),
-	{nil, 0, 0},
-};
-
-void
-rate(int i, u16int v)
-{
-	switch(i){
-	case 0: case 1:
-		sndch[i].finc = 131072ULL * 65536 / (srate * (2048 - (v & 0x7ff)));
-		break;
-	case 2:
-		sndch[2].finc = 2097152ULL * 65536 / (srate * (2048 - (v & 0x7ff)));
-		break;
-	case 3:
-		sndch[3].finc = 524288ULL * 65536 / srate;
-		if((v & 7) != 0)
-			sndch[3].finc /= v & 7;
-		else
-			sndch[3].finc <<= 1;
-		sndch[3].finc >>= (v >> 4 & 15) + 1;
-	}
-}
-
-void
-env(chan *c)
-{
-	if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<14) != 0)
-		--c->len;
-	if(c->len == 0){
-		c->vol = 0;
-		return;
-	}
-	if((envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
-		return;
-	c->ectr = *c->env >> 8 & 7;
-	if((*c->env & 1<<11) != 0){
-		if(c->vol < 15)
-			c->vol++;
-	}else
-		if(c->vol > 0)
-			c->vol--;
-}
-
-s8int
-wavesamp(void)
-{
-	s8int x;
-	u16int vol, cnt;
-	int v;
-
-	sndch[2].fctr = v = sndch[2].fctr + sndch[2].finc;
-	if(sndch[2].len == 0 || (reg[0x70/2] & 1<<7) == 0)
-		return 0;
-	vol = reg[0x72/2];
-	cnt = reg[0x70/2];
-	for(;;){
-		x = wave[wbank ^ wpos];
-		v -= 0x10000;
-		if(v < 0)
-			break;
-		wpos++;
-		if((cnt & 1<<5) != 0)
-			wpos &= 63;
-		else
-			wpos &= 31;
-	}
-	if((vol & 1<<15) != 0)
-		x = (x >> 2) + (x >> 3);
-	else if((vol & 3<<14) == 0)
-		x = 0;
-	else
-		x = x >> (vol >> 14 & 3);
-	return x;
-}
-
-s8int
-lfsrsamp(void)
-{
-	int v;
-	u16int l;
-
-	sndch[3].fctr = v = sndch[3].fctr + sndch[3].finc;
-	for(;;){
-		l = lfsr;
-		v -= 0x10000;
-		if(v < 0)
-			break;
-		lfsr >>= 1;
-		if(((l ^ lfsr) & 1) != 0)
-			if((reg[0x7c/2] & 1<<3) != 0)
-				lfsr |= 0x40;
-			else
-				lfsr |= 0x4000;
-	}
-	if((l & 1) != 0)
-		return -sndch[3].vol;
-	else
-		return sndch[3].vol;
-}
-
-void
-sweep(int wb)
-{
-	u16int fr;
-	int d;
-	u16int cnt;
-	
-	cnt = reg[0x60/2];
-	d = sweepfreq >> (cnt & 7);
-	if((cnt & 1<<3) != 0)
-		d = -d;
-	fr = sweepfreq + d;
-	if(fr > 2047){
-		sndch[0].len = 0;
-		sndch[0].vol = 0;
-		sweepen = 0;
-	}else if(wb){
-		sweepfreq = fr;
-		reg[0x64/2] = reg[0x64/2] & 0xfc00 | fr;
-		rate(0, fr);
-		sweep(0);
-	}
-}
-
-void
-sndstart(chan *c, u16int v)
-{
-	u16int cnt;
-
-	c->vol = *c->env >> 12;
-	c->ectr = *c->env >> 8 & 7;
-	if(c->len == 0)
-		c->len = 64;
-	if(c == sndch){
-		cnt = reg[0x60/2];
-		sweepen = (cnt & 0x07) != 0 && (cnt & 0x70) != 0;
-		sweepctr = cnt >> 4 & 7;
-		sweepfreq = v & 0x7ff;
-		if((cnt & 0x07) != 0)
-			sweep(0);
-	}
-}
-
-void
-sampletick(void *)
-{
-	u16int cntl, cnth;
-	s16int ch[6];
-	s16int s[2];
-	int i;
-	
-	addevent(&evsamp, sratediv);
-	
-	if(--envctr == 0){
-		envctr = envrel;
-		env(&sndch[0]);
-		env(&sndch[1]);
-		if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[0x74/2] & 1<<14) != 0)
-			sndch[2].len--;
-		env(&sndch[3]);
-		if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
-			sweepctr = reg[0x60/2] >> 4 & 7;
-			sweep(1);
-		}
-		envmod++;
-	}
-	
-	sndch[0].fctr += sndch[0].finc;
-	if(sndch[0].fctr >= sndch[0].fthr)
-		ch[0] = sndch[0].vol;
-	else
-		ch[0] = -sndch[0].vol;
-	sndch[1].fctr += sndch[1].finc;
-	if(sndch[1].fctr >= sndch[1].fthr)
-		ch[1] = sndch[1].vol;
-	else
-		ch[1] = -sndch[1].vol;
-	ch[2] = wavesamp();
-	ch[3] = lfsrsamp();
-	
-	cntl = reg[SOUNDCNTL];
-	cnth = reg[SOUNDCNTH];
-	for(i = 0; i < 4; i++)
-		ch[i] = ch[i] >> (cnth & 3);
-	ch[5] = snddma[0] << 1 + (cnth >> 2 & 1);
-	ch[6] = snddma[1] << 1 + (cnth >> 3 & 1);
-	
-	s[0] = 0;
-	s[1] = 0;
-	for(i = 0; i < 4; i++){
-		if((cntl & 1<<8<<i) != 0)
-			s[1] += ch[i] * (1 + (cntl & 7));
-		if((cntl & 1<<12<<i) != 0)
-			s[0] += ch[i] * (1 + (cntl >> 4 & 7));
-	}
-	for(i = 5; i < 6; i++){
-		if((cnth & 1<<3<<i) != 0)
-			s[1] += ch[i];
-		if((cnth & 1<<4<<i) != 0)
-			s[0] += ch[i]; 
-	}
-	s[0] += bias;
-	s[1] += bias;
-	if(s[0] < -0x200) s[0] = -0x200;
-	else if(s[0] > 0x1ff) s[0] = 0x1ff;
-	if(s[1] < -0x200) s[1] = -0x200;
-	else if(s[1] > 0x1ff) s[1] = 0x1ff;
-	
-	stime -= Freq;
-	while(stime < 0){
-		if(sbufp < sbuf + nelem(sbuf)){
-			sbufp[0] = s[0] << 6;
-			sbufp[1] = s[1] << 6;
-			sbufp += 2;
-		}
-		stime += srate;
-	}
-}
-
-
-void
-sndwrite(u16int a, u16int v)
-{
-	int sh, p, i;
-	static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
-	
-	switch(a){
-	case 0x62:
-		sndch[0].fthr = thr[v >> 6 & 3];
-		sndch[0].len = 64 - (v & 63);
-		break;
-	case 0x64:
-		rate(0, v);
-		if((v & 1<<15) != 0)
-			sndstart(&sndch[0], v);
-		break;
-	case 0x68:
-		sndch[1].fthr = thr[v >> 6 & 3];
-		break;
-	case 0x6c:
-		rate(1, v);
-		if((v & 1<<15) != 0)
-			sndstart(&sndch[1], v);
-		break;
-	case 0x70:
-		wbank = v >> 1 & 32;
-		break;
-	case 0x72:
-		sndch[2].len = 256 - (v & 0xff);
-		break;
-	case 0x74:
-		rate(2, v);
-		if((v & 1<<15) != 0 && sndch[2].len == 0)
-			sndch[2].len = 256;
-		break;
-	case 0x7c:
-		rate(3, v);
-		if((v & 1<<15) != 0){
-			if((v & 1<<3) != 0)
-				lfsr = 0x7f;
-			else
-				lfsr = 0x7fff;
-			sndstart(&sndch[3], v);
-		}
-		break;
-	case SOUNDBIAS*2:
-		sh = 9 - (v >> 14 & 3);
-		if(sratediv != 1<<sh){
-			srate = 1 << 24 - sh;
-			sratediv = 1 << sh;
-			envrel = srate / 512;
-			rate(0, reg[0x64/2]);
-			rate(1, reg[0x6c/2]);
-			rate(2, reg[0x74/2]);
-			rate(3, reg[0x7c/2]);
-		}
-		bias = (v & 0x3ff) - 0x200;
-		break;
-	case 0x90: case 0x92: case 0x94: case 0x96:
-	case 0x98: case 0x9a: case 0x9c: case 0x9e:
-		p = ~reg[0x70/2] >> 1 & 32;
-		for(i = a - 0x90; i < a - 0x90 + 2; i++){
-			wave[(wpos + 2 * i) & 31 + p] = v >> 4 & 0xf;
-			wave[(wpos + 2 * i + 1) & 31 + p] = v & 0xf;
-			v >>= 8;
-		}
-		break;
-	}
-}
-
-void
-audioinit(void)
-{
-	fd = open("/dev/audio", OWRITE);
-	if(fd < 0)
-		sysfatal("open: %r");
-	sbufp = sbuf;
-	sndwrite(SOUNDBIAS*2, 0x200);
-	evsamp.f = sampletick;
-	addevent(&evsamp, sratediv);
-}
-
-int
-audioout(void)
-{
-	int rc;
-	static int cl;
-	static vlong t0;
-
-	if(t0 == 0)
-		t0 = nsec();
-	if(sbufp == nil)
-		return -1;
-	if(sbufp == sbuf)
-		return 0;
-	cl = clock;
-	vlong t = nsec();
-	rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2);
-	vlong t2 = nsec();
-	double Δ = (t2 - t) / 1000000.0;
-	double τ = (t2 - t0) / 1000000.0;
-	double τ0 = rc * 1000.0 / (44100.0 * 4);
-	fprint(2, "%d %f %f\n", rc, Δ, τ-τ0);
-	t0 = t2;
-	if(rc > 0)
-		sbufp -= (rc+1)/2;
-	if(sbufp < sbuf)
-		sbufp = sbuf;
-	return 0;
-}
--- a/sys/src/games/gba/ppu.c
+++ /dev/null
@@ -1,781 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int hblank, ppuy;
-u8int bldy, blda, bldb;
-u32int hblclock;
-int ppux0;
-u32int pixcol[480];
-u8int pixpri[480];
-u8int pixwin[240];
-int objalpha;
-
-typedef struct bg bg;
-struct bg {
-	uchar n;
-	s32int rpx0, rpy0, rpx1, rpy1, rpx, rpy;
-	u16int tx, ty;
-	u8int tnx, tny;
-	
-	u8int mosaic, mctr, lasti;
-	u32int curc;
-	u8int curpri;
-};
-static bg bgst[4] = {{.n = 0}, {.n = 1}, {.n = 2}, {.n = 3}};
-
-Var ppuvars[] = {
-	VAR(hblank), VAR(ppuy), VAR(hblclock),
-	VAR(bldy), VAR(blda), VAR(bldb), VAR(objalpha),
-	VAR(bgst[2].rpx0), VAR(bgst[2].rpy0), VAR(bgst[3].rpx0), VAR(bgst[3].rpy0),
-	{nil, 0, 0},
-};
-
-typedef struct sprite sprite;
-struct sprite {
-	uchar w, wb, h;
-	s16int x;
-	uchar ysh;
-	
-	uchar *base;
-	u16int *pal;
-	u16int inc;
-
-	u32int t0;
-	u16int t1;
-	uchar depth;
-	
-	s32int rx, ry;
-	s16int dx, dy;
-	
-	u8int mctr, mcol;
-};
-static sprite sprt[128], *sp = sprt;
-enum {
-	SPRROT = 1<<8,
-	SPRDIS = 1<<9,
-	SPRDOUB = 1<<9,
-	SPRMOSA = 1<<12,
-	SPR8 = 1<<13,
-	SPRWIDE = 1<<14,
-	SPRTALL = 1<<15,
-	SPRHFLIP = 1<<28,
-	SPRVFLIP = 1<<29,
-	SPRSIZE0 = 1<<30,
-	SPRSIZE1 = 1<<31,
-
-	NOWIN = 0,
-	OBJWIN = 1,
-	WIN2 = 2,
-	WIN1 = 4,
-	
-	OBJALPHA = 1<<16,
-	SRCOBJ = 4<<17,
-	SRCBACK = 5<<17,
-	
-	VACANT = 0x10,
-	BACKDROP = 8,
-};
-#define SRCBG(n) ((n)<<17)
-
-void
-sprinit(void)
-{
-	u16int *p, *pp;
-	u16int cnt, t1;
-	u32int t0;
-	int budg;
-	uchar ws, h, hb, d, dy, s;
-	static uchar wss[16] = {3, 4, 5, 6, 4, 5, 5, 6, 3, 3, 4, 5};
-	static uchar hss[16] = {3, 4, 5, 6, 3, 3, 4, 5, 4, 5, 5, 6};
-
-	sp = sprt;
-	cnt = reg[DISPCNT];
-	budg = (cnt & HBLFREE) != 0 ? 954 : 1210;
-	for(p = oam; p < oam + 512; p += 4){
-		t0 = p[0];
-		if((t0 & (SPRROT|SPRDIS)) == SPRDIS)
-			continue;
-		t0 |= p[1] << 16;
-		s = t0 >> 30 & 3 | t0 >> 12 & 12;
-		hb = h = 1 << hss[s];
-		dy = ppuy - (u8int) t0;
-		if((t0 & (SPRROT|SPRDOUB)) == (SPRROT|SPRDOUB))
-			hb <<= 1;
-		if(dy >= hb || (u8int)t0 + hb > 256 && ppuy + 256 - (u8int)t0 >= hb)
-			continue;
-		if((t0 & SPRMOSA) != 0){
-			dy = dy - dy % ((reg[MOSAIC] >> 12 & 15) + 1);
-			sp->mctr = 0;
-		}
-		sp->x = (s32int)(t0 << 7) >> 23;
-		sp->t0 = t0;
-		ws = wss[s];
-		sp->wb = sp->w = 1<<ws;
-		sp->h = h;
-		sp->t1 = t1 = p[2];
-		sp->base = vram + 0x10000 + ((t1 & 0x3ff) << 5);
-		d = (t0 & SPR8) != 0;
-		sp->ysh = (cnt & OBJNOMAT) != 0 ? 2 + d + ws : 10;
-		if((t0 & SPRROT) != 0){
-			if((t0 & SPRDOUB) != 0)
-				sp->wb <<= 1;
-			budg -= 10 + sp->w*2;
-			pp = oam + 3 + (t0 >> 21 & 0x1f0);
-			sp->dx = pp[0];
-			sp->dy = pp[8];
-			sp->rx = (dy - hb/2) * (s16int) pp[4] + (sp->w << 7) - sp->dx * sp->wb/2;
-			sp->ry = (dy - hb/2) * (s16int)pp[12] + (sp->h << 7) - sp->dy * sp->wb/2;
-			if(sp->x < 0){
-				sp->rx -= sp->x * sp->dx;
-				sp->ry -= sp->x * sp->dy;
-			}
-		}else{
-			budg -= sp->w;
-			if((t0 & SPRVFLIP) != 0)
-				dy = h - 1 - dy;
-			sp->base += (dy & 7) << 2 + d;
-			sp->base += dy >> 3 << sp->ysh;
-			if((t0 & SPRHFLIP) != 0)
-				sp->base += sp->w - 7 << 2 + d;
-			sp->inc = (1 << 5 + d) - (1 << 2 + d);
-			if(sp->x < 0)
-				if((t0 & SPRHFLIP) != 0){
-					sp->base -= ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
-					if((t0 & SPR8) == 0 && (sp->x & 1) != 0)
-						sp->base--;
-				}else
-					sp->base += ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
-		}
-		if((t0 & SPR8) != 0)
-			sp->pal = pram + 0x100;
-		else
-			sp->pal = pram + 0x100 + (t1 >> 8 & 0xf0);
-		if(budg < 0)
-			break;
-		sp++;
-	}
-}
-
-void
-spr(int x1)
-{
-	int x0, i, dx, sx0, sx1;
-	u8int pri, v, d, *b;
-	u16int x, y;
-	u32int c, t0;
-	sprite *s;
-	
-	x0 = ppux0;
-	for(s = sprt; s < sp; s++){
-		if(s->x >= x1 || s->x + s->wb <= x0)
-			continue;
-		t0 = s->t0;
-		pri = s->t1 >> 10 & 3;
-		sx0 = s->x >= x0 ? s->x : x0;
-		sx1 = s->x + s->wb;
-		if(x1 < sx1)
-			sx1 = x1;
-		dx = sx0 - s->x;
-		for(i = sx0; i < sx1; i++, dx++){
-			if((t0 & SPRROT) != 0){
-				d = (t0 & SPR8) != 0;
-				x = s->rx >> 8;
-				y = s->ry >> 8;
-				s->rx += s->dx;
-				s->ry += s->dy;
-				if(x < s->w && y < s->h){
-					b = s->base;
-					b += (y & 7) << 2 + d;
-					b += y >> 3 << s->ysh;
-					b += (x & 7) >> 1 - d;
-					b += x >> 3 << 5 + d;
-					v = *b;
-					if(!d)
-						if((x & 1) != 0)
-							v >>= 4;
-						else
-							v &= 0xf;
-				}else
-					v = 0;
-			}else if((t0 & SPRHFLIP) != 0){
-				if((t0 & SPR8) != 0)
-					v = *--s->base;
-				else if((dx & 1) != 0)
-					v = *s->base & 0x0f;
-				else
-					v = *--s->base >> 4;
-				if((dx & 7) == 7)
-					s->base -= s->inc;
-			}else{
-				v = *s->base;
-				if((t0 & SPR8) != 0)
-					s->base++;
-				else if((dx & 1) != 0){
-					v >>= 4;
-					s->base++;
-				}else
-					v &= 0xf;
-				if((dx & 7) == 7)
-					s->base += s->inc;
-			}
-			if((t0 & SPRMOSA) != 0)
-				if(s->mctr == 0){
-					s->mctr = reg[MOSAIC] >> 8 & 15;
-					s->mcol = v;
-				}else{
-					--s->mctr;
-					v = s->mcol;
-				}
-			if(v != 0){
-				c = s->pal[v] | SRCOBJ;
-				switch(t0 >> 10 & 3){
-				case 1:
-					c |= OBJALPHA;
-					objalpha++;
-				case 0:
-					if(pri < pixpri[i]){
-						pixcol[i] = c;
-						pixpri[i] = pri;
-					}
-					break;
-				case 2:
-					if((reg[DISPCNT] & 1<<15) != 0)
-						pixwin[i] |= OBJWIN;
-					break;
-				}
-			}
-		}
-	}
-}
-
-void
-bgpixel(bg *b, int i, u32int c, int pri)
-{
-	u8int *p;
-	u32int *q;
-	int j;
-
-	if(b != nil){
-		c |= SRCBG(b->n);
-		if(b->mosaic){
-			for(j = (u8int)(b->lasti+1); j <= i; j++){
-				if(b->mctr == 0){
-					if(j == i){
-						b->curc = c;
-						b->curpri = pri;
-					}else
-						b->curpri = VACANT;
-					b->mctr = reg[MOSAIC] & 15;
-				}else
-					b->mctr--;
-				if(b->curpri != VACANT && (pixwin[j] & 1<<b->n) == 0)
-					bgpixel(nil, j, b->curc, b->curpri);
-			}
-			b->lasti = i;
-			return;
-		}
-	}
-	p = pixpri + i;
-	q = pixcol + i;
-	if(pri < p[0]){
-		p[240] = p[0];
-		p[0] = pri;
-		q[240] = q[0];
-		q[0] = c;
-	}else if(pri < p[240]){
-		p[240] = pri;
-		q[240] = c;
-	}
-}
-
-
-
-void
-bginit(bg *b, int scal, int)
-{
-	u16int x, y;
-	u16int *rr;
-	int msz;
-
-	b->mosaic = (reg[BG0CNT + b->n] & BGMOSAIC) != 0;
-	if(b->mosaic){
-		b->mctr = 0;
-		b->lasti = -1;
-	}
-	if(scal){
-		rr = reg + (b->n - 2 << 3);
-		if(ppuy == 0){
-			b->rpx0 = (s32int)(rr[BG2XL] | rr[BG2XH] << 16) << 4 >> 4;
-			b->rpy0 = (s32int)(rr[BG2YL] | rr[BG2YH] << 16) << 4 >> 4;
-		}
-		if(!b->mosaic || ppuy % ((reg[MOSAIC] >> 4 & 15) + 1) == 0){
-			b->rpx1 = b->rpx0;
-			b->rpy1 = b->rpy0;
-		}
-		b->rpx = b->rpx1;
-		b->rpy = b->rpy1;
-		b->rpx0 += (s16int)rr[BG2PB];
-		b->rpy0 += (s16int)rr[BG2PD];
-	}else{
-		rr = reg + (b->n << 1);
-		x = rr[BG0HOFS] & 0x1ff;
-		y = ppuy;
-		if(b->mosaic){
-			msz = (reg[MOSAIC] >> 4 & 15) + 1;
-			y = y - y % msz;
-		}
-		y += (rr[BG0VOFS] & 0x1ff);
-		b->tx = x >> 3;
-		b->ty = y >> 3;
-		b->tnx = x & 7;
-		b->tny = y & 7;
-	}
-}
-
-void
-bgsinit(void)
-{
-	switch(reg[DISPCNT] & 7){
-	case 0:
-		bginit(&bgst[0], 0, 0);
-		bginit(&bgst[1], 0, 0);
-		bginit(&bgst[2], 0, 0);
-		bginit(&bgst[3], 0, 0);
-		break;
-	case 1:
-		bginit(&bgst[0], 0, 0);
-		bginit(&bgst[1], 0, 0);
-		bginit(&bgst[2], 1, 0);
-		break;
-	case 2:
-		bginit(&bgst[2], 1, 0);
-		bginit(&bgst[3], 1, 0);
-		break;
-	case 3:
-	case 4:
-	case 5:
-		bginit(&bgst[2], 1, 1);
-		break;
-	}	
-}
-
-void
-bitbg(bg *b, int x1)
-{
-	u8int *base, *p, pri, d;
-	u16int cnt, *rr, sx, sy;
-	int i, v;
-	
-	cnt = reg[DISPCNT];
-	if((cnt & 1<<8 + b->n) == 0)
-		return;
-	rr = reg + (b->n - 2 << 3);
-	if((cnt & 7) != 5){
-		sx = 240 << 8;
-		sy = 160 << 8;
-		d = (cnt & 7) == 3;
-	}else{
-		sx = 160 << 8;
-		sy = 128 << 8;
-		d = 1;
-	}
-	base = vram;
-	if((cnt & FRAME) != 0 && (cnt & 7) != 3)
-		base += 0xa000;
-	pri = reg[BG0CNT + b->n] & 3;
-	for(i = ppux0; i < x1; i++){
-		if(((pixwin[i] & 1<<b->n) == 0 || b->mosaic) && (u32int)b->rpx < sx && (u32int)b->rpy < sy){
-			if(d){
-				p = base + 2 * (b->rpx >> 8) + 480 * (b->rpy >> 8);
-				v = p[0] | p[1] << 8;
-			}else{
-				v = base[(b->rpx >> 8) + 240 * (b->rpy >> 8)];
-				if(v != 0)
-					v = pram[v];
-				else
-					v = -1;
-			}
-			if(v >= 0)
-				bgpixel(b, i, v, pri);
-	
-		}
-		b->rpx += (s16int) rr[BG2PA];
-		b->rpy += (s16int) rr[BG2PC];
-	}
-}
-
-void
-txtbg(bg *b, int x1)
-{
-	u8int y, v, d, *cp;
-	u16int bgcnt, ta0, ta, tx, ty, t, *pal;
-	u32int ca;
-	int i, x, mx;
-	
-	if((reg[DISPCNT] & 1<<8 + b->n) == 0)
-		return;
-	bgcnt = reg[BG0CNT + b->n];
-	d = bgcnt >> 7 & 1;
-	tx = b->tx;
-	ty = b->ty;
-	ta0 = (bgcnt << 3 & 0xf800) + ((ty & 0x1f) << 6);
-	switch(bgcnt >> 14){
-	case 2: ta0 += ty << 6 & 0x800; break;
-	case 3: ta0 += ty << 7 & 0x1000; break;
-	}
-	x = ppux0;
-	i = b->tnx;
-	for(; x < x1; tx++, i = 0){
-		ta = ta0 + ((tx & 0x1f) << 1);
-		if((bgcnt & 1<<14) != 0)
-			ta += tx << 6 & 0x800;
-		t = vram[ta] | vram[ta+1] << 8;
-		if(d)
-			pal = pram;
-		else
-			pal = pram + (t >> 8 & 0xf0);
-		ca = (bgcnt << 12 & 0xc000) + ((t & 0x3ff) << 5+d);
-		if(ca >= 0x10000)
-			continue;
-		y = b->tny;
-		if((t & 1<<11) != 0)
-			y ^= 7;
-		ca += y << 2+d;
-		cp = vram + ca;
-		for(; i < 8; i++, x++){
-			if(x >= x1)
-				goto out;
-			if((pixwin[x] & 1<<b->n) != 0 && !b->mosaic)
-				continue;
-			mx = i;
-			if((t & 1<<10) != 0)
-				mx ^= 7;
-			v = cp[mx >> 1-d];
-			if(!d)
-				if((mx & 1) != 0)
-					v >>= 4;
-				else
-					v &= 0xf;
-			if(v != 0)
-				bgpixel(b, x, pal[v], bgcnt & 3);
-		}
-	}
-out:
-	b->tx = tx;
-	b->tnx = i;
-}
-
-void
-rotbg(bg *b, int x1)
-{
-	uchar *p, v;
-	u16int bgcnt, *rr, ta;
-	int i, row, sz, x, y;
-
-	rr = reg + (b->n - 2 << 3);
-	if((reg[DISPCNT] & 1<<8 + b->n) == 0)
-		return;
-	bgcnt = reg[BG0CNT + b->n];
-	row = (bgcnt >> 14) + 4;
-	sz = 1 << 3 + row;
-	for(i = ppux0; i < x1; i++){
-		x = b->rpx >> 8;
-		y = b->rpy >> 8;
-		b->rpx += (s16int) rr[BG2PA];
-		b->rpy += (s16int) rr[BG2PC];
-		if((pixwin[i] & 1<<b->n) != 0 && !b->mosaic)
-			continue;
-		if((bgcnt & DISPWRAP) != 0){
-			x &= sz - 1;
-			y &= sz - 1;
-		}else if((uint)x >= sz || (uint)y >= sz)
-			 continue;
-		ta = (bgcnt << 3 & 0xf800) + ((y >> 3) << row) + (x >> 3);
-		p = vram + (bgcnt << 12 & 0xc000) + (vram[ta] << 6);
-		p += (x & 7) + ((y & 7) << 3);
-		if((v = *p) != 0)
-			bgpixel(b, i, pram[v], bgcnt & 3);
-		
-	}
-}
-
-void
-windows(int x1)
-{
-	static u8int wintab[8] = {2, 3, 1, 1, 0, 0, 0, 0};
-	int i, sx0, sx1;
-	u16int v, h;
-	u16int cnt;
-	
-	cnt = reg[DISPCNT];
-	if((cnt >> 13) != 0){
-		if((cnt & 1<<13) != 0){
-			v = reg[WIN0V];
-			h = reg[WIN0H];
-			if(ppuy < (u8int)v && ppuy >= v >> 8){
-				sx1 = (u8int)h;
-				sx0 = h >> 8;
-				if(sx0 < ppux0)
-					sx0 = ppux0;
-				if(sx1 > x1)
-					sx1 = x1;
-				for(i = sx0; i < sx1; i++)
-					pixwin[i] |= WIN1;
-			}
-		}
-		if((cnt & 1<<14) != 0){
-			v = reg[WIN1V];
-			h = reg[WIN1H];
-			if(ppuy < (u8int)v && ppuy >= v >> 8){
-				sx1 = (u8int)h;
-				sx0 = h >> 8;
-				if(sx0 < ppux0)
-					sx0 = ppux0;
-				if(sx1 > x1)
-					sx1 = x1;
-				for(i = sx0; i < sx1; i++)
-					pixwin[i] |= WIN2;
-			}
-		}
-		for(i = ppux0; i < x1; i++){
-			v = wintab[pixwin[i]];
-			h = reg[WININ + (v & 2) / 2];
-			if((v & 1) != 0)
-				h >>= 8;
-			pixwin[i] = ~h;
-		}
-	}
-	for(i = ppux0; i < x1; i++)
-		if(pixpri[i] == VACANT || (pixwin[i] & 1<<4) != 0){
-			pixcol[i] = pram[0] | SRCBACK;
-			pixpri[i] = BACKDROP;
-		}else{
-			pixcol[i+240] = pram[0] | SRCBACK;
-			pixpri[i+240] = BACKDROP;
-		}
-	objalpha = 0;
-}
-
-u16int
-mix(u16int c1, u16int c2)
-{
-	u16int r, g, b, eva, evb;
-
-	eva = blda;
-	evb = bldb;
-	b = ((c1 & 0x7c00) * eva + (c2 & 0x7c00) * evb) >> 4;
-	g = ((c1 & 0x03e0) * eva + (c2 & 0x03e0) * evb) >> 4;
-	r = ((c1 & 0x001f) * eva + (c2 & 0x001f) * evb) >> 4;
-	if(b > 0x7c00) b = 0x7c00;
-	if(g > 0x03e0) g = 0x03e0;
-	if(r > 0x001f) r = 0x001f;
-	return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-u16int
-brighten(u16int c1)
-{
-	u16int r, g, b, y;
-	
-	y = bldy;
-	b = c1 & 0x7c00;
-	b = b + (0x7c00 - b) * y / 16;
-	g = c1 & 0x03e0;
-	g = g + (0x03e0 - g) * y / 16;
-	r = c1 & 0x001f;
-	r = r + (0x001f - r) * y / 16;
-	if(b > 0x7c00) b = 0x7c00;
-	if(g > 0x03e0) g = 0x03e0;
-	if(r > 0x001f) r = 0x001f;
-	return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-u16int
-darken(u16int c1)
-{
-	u16int r, g, b, y;
-
-	y = 16 - bldy;
-	b = c1 & 0x7c00;
-	b = b * y / 16;
-	g = c1 & 0x03e0;
-	g = g * y / 16;
-	r = c1 & 0x001f;
-	r = r * y / 16;
-	return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-void
-colormath(int x1)
-{
-	u16int bldcnt;
-	u32int *p;
-	int i;
-	
-	bldcnt = reg[BLDCNT];
-	if((bldcnt & 3<<6) == 0 && objalpha == 0)
-		return;
-	p = pixcol + ppux0;
-	for(i = ppux0; i < x1; i++, p++){
-		if((*p & OBJALPHA) != 0)
-			goto alpha;
-		if((pixwin[i] & 1<<5) != 0 || (bldcnt & 1<<(*p >> 17)) == 0)
-			continue;
-		switch(bldcnt >> 6 & 3){
-		case 1:
-		alpha:
-			if((bldcnt & 1<<8+(p[240] >> 17)) == 0)
-				continue;
-			*p = mix(*p, p[240]);
-			break;
-		case 2:
-			*p = brighten(*p);
-			break;
-		case 3:
-			*p = darken(*p);
-			break;
-		}
-	}
-}
-
-void
-syncppu(int x1)
-{
-	int i;
-	u16int cnt;
-
-	if(hblank || ppuy >= 160)
-		return;
-	if(x1 >= 240)
-		x1 = 240;
-	else if(x1 <= ppux0)
-		return;
-	cnt = reg[DISPCNT];
-	if((cnt & FBLANK) != 0){
-		for(i = ppux0; i < x1; i++)
-			pixcol[i] = 0xffff;
-		ppux0 = x1;
-		return;
-	}
-
-	if((cnt & 1<<12) != 0)
-		spr(x1);
-	windows(x1);
-	switch(cnt & 7){
-	case 0:
-		txtbg(&bgst[0], x1);
-		txtbg(&bgst[1], x1);
-		txtbg(&bgst[2], x1);
-		txtbg(&bgst[3], x1);
-		break;
-	case 1:
-		txtbg(&bgst[0], x1);
-		txtbg(&bgst[1], x1);
-		rotbg(&bgst[2], x1);
-		break;
-	case 2:
-		rotbg(&bgst[2], x1);
-		rotbg(&bgst[3], x1);
-		break;
-	case 3:
-	case 4:
-	case 5:
-		bitbg(&bgst[2], x1);
-	}
-	colormath(x1);
-	ppux0 = x1;
-}
-
-void
-linecopy(u32int *p, int y)
-{
-	uchar *q;
-	u16int *r;
-	u16int v;
-	union { u16int w; u8int b[2]; } u;
-	int n;
-
-	q = pic + y * 240 * 2;
-	r = (u16int*)q;
-	n = 240;
-	while(n--){
-		v = *p++;
-		u.b[0] = v;
-		u.b[1] = v >> 8;
-		*r++ = u.w;
-	}
-}
-
-void
-hblanktick(void *)
-{
-	extern Event evhblank;
-	u16int stat;
-
-	stat = reg[DISPSTAT];
-	if(hblank){
-		hblclock = clock + evhblank.time;
-		addevent(&evhblank, 240*4);
-		hblank = 0;
-		ppux0 = 0;
-		memset(pixpri, VACANT, sizeof(pixpri));
-		memset(pixwin, 0, 240);
-		if(++ppuy >= 228){
-			ppuy = 0;
-			flush();
-		}
-		if(ppuy < 160){
-			sprinit();
-			bgsinit();
-		}else if(ppuy == 160){
-			dmastart(DMAVBL);
-			if((stat & IRQVBLEN) != 0)
-				setif(IRQVBL);
-		}
-		if((stat & IRQVCTREN) != 0 && ppuy == stat >> 8)
-			setif(IRQVCTR);
-	}else{
-		syncppu(240);
-		if(ppuy < 160)
-			linecopy(pixcol, ppuy);
-		addevent(&evhblank, 68*4);
-		hblank = 1;
-		if((stat & IRQHBLEN) != 0)
-			setif(IRQHBL);
-		if(ppuy < 160)
-			dmastart(DMAHBL);
-	}
-}
-
-void
-ppuwrite(u16int a, u16int v)
-{
-	syncppu((clock - hblclock) / 4);
-	switch(a){
-	case BLDALPHA*2:
-		blda = v & 0x1f;
-		if(blda > 16)
-			blda = 16;
-		bldb = v >> 8 & 0x1f;
-		if(bldb > 16)
-			bldb = 16;
-		break;
-	case BLDY*2:
-		bldy = v & 0x1f;
-		if(bldy > 16)
-			bldy = 16;
-		break;
-	case BG2XL*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff0000 | v; break;
-	case BG2XH*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
-	case BG2YL*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff0000 | v; break;
-	case BG2YH*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;
-	case BG3XL*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff0000 | v; break;
-	case BG3XH*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
-	case BG3YL*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff0000 | v; break;
-	case BG3YH*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;
-	}
-}
--- a/sys/src/games/md/vdp.c
+++ /dev/null
@@ -1,378 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-u16int vdpstat = 0x3400;
-int vdpx, vdpy, vdpyy, frame, intla;
-u16int hctr;
-static int xmax, xdisp;
-static int sx, snx, col, pri, lum;
-enum { DARK, NORM, BRIGHT };
-enum { ymax = 262, yvbl = 234 };
-
-void
-vdpmode(void)
-{
-	if((reg[MODE4] & WIDE) != 0){
-		xmax = 406;
-		xdisp = 320;
-	}else{
-		xdisp = 256;
-		xmax = 342;
-	}
-	intla = (reg[MODE4] & 6) == 6;
-}
-
-static void
-pixeldraw(int x, int y, int v)
-{
-	u32int *p;
-	union { u32int l; u8int b[4]; } u;
-
-	u.b[0] = v >> 16;
-	u.b[1] = v >> 8;
-	u.b[2] = v;
-	u.b[3] = 0;
-	*((u32int *)pic + (x + y * 320)) = u.l;
-}
-
-static u32int
-shade(u32int v, int l)
-{
-	if(l == 1)
-		return v;
-	if(l == 2)
-		return v << 1 & 0xefefef;
-	return v >> 1 & 0xf7f7f7;
-}
-
-static void
-pixel(int v, int p)
-{
-	if(p >= pri){
-		col = v;
-		pri = p;
-	}
-}
-
-struct pctxt {
-	u8int ws, w, hs, h;
-	u16int tx, ty;
-	u8int tnx, tny;
-	u16int t;
-	u32int c;
-} pctxt[3];
-int lwin, rwin;
-
-static void
-tile(struct pctxt *p)
-{
-	u16int a;
-	int y;
-	
-	switch(p - pctxt){
-	default: a = (reg[PANT] & 0x38) << 9; break;
-	case 1: a = (reg[PBNT] & 7) << 12; break;
-	case 2: a = (reg[PWNT] & 0x3e) << 9; break;
-	}
-	a += p->ty << p->ws;
-	a += p->tx;
-	p->t = vram[a];
-	y = p->tny;
-	if(intla){
-		if((p->t & 0x1000) != 0)
-			y = 15 - y;
-		a = (p->t & 0x7ff) << 5 | y << 1;
-	}else{
-		if((p->t & 0x1000) != 0)
-			y = 7 - y;
-		a = (p->t & 0x7ff) << 4 | y << 1;
-	}
-	p->c = vram[a] << 16 | vram[a+1];
-}
-
-static void
-planeinit(void)
-{
-	static int szs[] = {5, 6, 6, 7};
-	int v, a, i;
-	struct pctxt *p;
-	
-	pctxt[0].hs = pctxt[1].hs = szs[reg[PLSIZ] >> 4 & 3];
-	pctxt[0].ws = pctxt[1].ws = szs[reg[PLSIZ] & 3];
-	pctxt[2].ws = (reg[MODE4] & WIDE) != 0 ? 6 : 5;
-	pctxt[2].hs = 5;
-	for(i = 0; i <= 2; i++){
-		pctxt[i].h = 1<<pctxt[i].hs;
-		pctxt[i].w = 1<<pctxt[i].ws;
-	}
-	a = reg[HORSCR] << 9 & 0x7fff;
-	switch(reg[MODE3] & 3){
-	case 1: a += vdpy << 1 & 0xe; break;
-	case 2: a += vdpy << 1 & 0xff0; break;
-	case 3: a += vdpy << 1 & 0xffe; break;
-	}
-	for(i = 0; i < 2; i++){
-		p = pctxt + i;
-		v = -(vram[a + i] & 0x3ff);
-		p->tnx = v & 7;
-		p->tx = v >> 3 & pctxt[i].w - 1;
-		if(intla){
-			v = vsram[i] + vdpyy;
-			p->tny = v & 15;
-			p->ty = v >> 4 & pctxt[i].h - 1;
-		}else{
-			v = vsram[i] + vdpy;
-			p->tny = v & 7;
-			p->ty = v >> 3 & pctxt[i].h - 1;
-		}
-		tile(p);
-		if(p->tnx != 0)
-			if((p->t & 0x800) != 0)
-				p->c >>= p->tnx << 2;
-			else
-				p->c <<= p->tnx << 2;
-	}
-	sx = 0;
-	snx = 0;
-	v = reg[WINV] << 3 & 0xf8;
-	if((reg[WINV] & 0x80) != 0 ? vdpy < v : vdpy >= v){
-		lwin = 0;
-		rwin = reg[WINH] << 4 & 0x1f0;
-		if((reg[WINH] & 0x80) != 0){
-			lwin = rwin;
-			rwin = 320;
-		}
-	}else{
-		lwin = 0;
-		rwin = 320;
-	}
-	if(rwin > lwin){
-		p = pctxt + 2;
-		p->tx = lwin >> 3 & pctxt[2].w - 1;
-		p->tnx = lwin & 7;
-		p->tny = vdpy & 7;
-		p->ty = vdpy >> 3 & pctxt[2].h - 1;
-		tile(p);
-	}
-}
-
-static void
-plane(int n, int vis)
-{
-	struct pctxt *p;
-	u8int v, pr;
-	
-	p = pctxt + n;
-	if((p->t & 0x800) != 0){
-		v = p->c & 15;
-		p->c >>= 4;
-	}else{
-		v = p->c >> 28;
-		p->c <<= 4;
-	}
-	if(vis != 0){
-		if(v != 0){
-			v |= p->t >> 9 & 48;
-			pr = 2 - (n & 1) + (p->t >> 13 & 4);
-			pixel(v, pr);
-		}
-		lum |= p->t >> 15;
-	}
-	if(++p->tnx == 8){
-		p->tnx = 0;
-		if(++p->tx == p->w)
-			p->tx = 0;
-		tile(pctxt + n);
-	}
-}
-
-static void
-planes(void)
-{
-	int i, w;
-	u16int v;
-
-	if((reg[MODE3] & 4) != 0 && ++snx == 16){
-		snx = 0;
-		sx++;
-		for(i = 0; i < 2; i++){
-			v = vsram[sx + i] + vdpy;
-			pctxt[i].tny = v & 7;
-			pctxt[i].ty = v >> 3 & pctxt[i].h - 1;
-		}
-	}
-	w = vdpx < rwin && vdpx >= lwin;
-	plane(0, !w);
-	plane(1, 1);
-	if(w)
-		plane(2, 1);
-}
-
-static struct sprite {
-	u16int y, x;
-	u8int w, h;
-	u16int t;
-	u32int c[4];
-} spr[21], *lsp;
-
-static void
-spritesinit(void)
-{
-	u16int t, *p, dy, c;
-	u32int v;
-	int i, ns, np, nt;
-	struct sprite *q;
-	
-	t = (reg[SPRTAB] << 8 & 0x7f00);
-	p = vram + t;
-	q = spr;
-	ns = (reg[MODE4] & WIDE) != 0 ? 20 : 16;
-	np = 0;
-	nt = 0;
-	do{
-		if(intla){
-			q->y = (p[0] & 0x3ff) - 256;
-			q->h = (p[1] >> 8 & 3) + 1 << 4;
-			dy = vdpyy - q->y;
-		}else{
-			q->y = (p[0] & 0x3ff) - 128;
-			q->h = (p[1] >> 8 & 3) + 1 << 3;
-			dy = vdpy - q->y;
-		}
-		if(dy >= q->h)
-			continue;
-		q->t = p[2];
-		if((q->t & 0x1000) != 0)
-			dy = q->h + ~dy;
-		q->x = (p[3] & 0x3ff) - 128;
-		if(q->x == 0xff80)
-			break;
-		q->w = (p[1] >> 10 & 3) + 1 << 3;
-		c = ((q->t & 0x7ff) << 4+intla) + (dy << 1);
-		for(i = 0; i < q->w >> 3 && np < xdisp; i++){
-			v = vram[c] << 16 | vram[(u16int)(c+1)];
-			c += q->h << 1;
-			if((q->t & 0x800) != 0)
-				q->c[(q->w >> 3) - 1 - i] = v;
-			else
-				q->c[i] = v;
-			np += 8;
-		}
-		if((u16int)-q->x < q->w){
-			i = -(s16int)q->x;
-			if((q->t & 0x800) != 0)
-				q->c[i>>3] >>= (i & 7) << 2;
-			else
-				q->c[i>>3] <<= (i & 7) << 2;
-		}
-		if(++q == spr + ns || np >= xdisp){
-			vdpstat |= STATOVR;
-			break;
-		}
-	}while(p = vram + (u16int)(t + ((p[1] & 0x7f) << 2)), p - vram != t && ++nt < 80);
-	lsp = q;
-}
-
-static void
-sprites(void)
-{
-	struct sprite *p;
-	u16int dx;
-	int v, col, set;
-	u32int *c;
-	
-	set = 0;
-	col = 0;
-	for(p = spr; p < lsp; p++){
-		dx = vdpx - p->x;
-		if(dx >= p->w)
-			continue;
-		c = p->c + (dx >> 3);
-		if((p->t & 0x800) != 0){
-			v = *c & 15;
-			*c >>= 4;
-		}else{
-			v = *c >> 28;
-			*c <<= 4;
-		}
-		if(v != 0)
-			if(set != 0)
-				vdpstat |= STATCOLL;
-			else{
-				set = 1 | p->t & 0x8000;
-				col = p->t >> 9 & 48 | v;
-			}
-	}
-	if(set)
-		if((reg[MODE4] & SHI) != 0)
-			if((col & 0xfe) == 0x3e)
-				lum = col & 1;
-			else{
-				pixel(col, set >> 13 | 2);
-				if((col & 0xf) == 0xe)
-					lum = 1;
-				else
-					lum |= set >> 15;
-			}
-		else
-			pixel(col, set >> 13 | 2);
-}
-
-void
-vdpstep(void)
-{
-	u32int v;
-
-	if(vdpx == 0){
-		planeinit();
-		spritesinit();
-	}
-	if(vdpx < 320 && vdpy < 224)
-		if(vdpx < xdisp){
-			col = reg[BGCOL] & 0x3f;
-			pri = 0;
-			lum = 0;
-			planes();
-			sprites();
-			if((reg[MODE2] & 0x40) != 0 && (vdpx >= 8 || (reg[MODE1] & 0x20) == 0)){
-				v = cramc[col];
-				if((reg[MODE4] & SHI) != 0)
-					v = shade(v, lum);
-				pixeldraw(vdpx, vdpy, v);
-			}else
-				pixeldraw(vdpx, vdpy, 0);
-		}else
-			pixeldraw(vdpx, vdpy, 0xcccccc);
-	if(++vdpx >= xmax){
-		z80irq = 0;
-		vdpx = 0;
-		if(++vdpy >= ymax){
-			vdpy = 0;
-			irq &= ~INTVBL;
-			vdpstat ^= STATFR;
-			vdpstat &= ~(STATINT | STATVBL | STATOVR | STATCOLL);
-			flush();
-		}
-		if(intla)
-			vdpyy = vdpy << 1 | frame;
-		if(vdpy == 0 || vdpy >= 225)
-			hctr = reg[HORCTR];
-		else
-			if(hctr-- == 0){
-				if((reg[MODE1] & IE1) != 0)
-					irq |= INTHOR;
-				hctr = reg[HORCTR];
-			}
-		if(vdpy == yvbl){
-			vdpstat |= STATVBL | STATINT;
-			frame ^= 1;
-			z80irq = 1;
-			if((reg[MODE2] & IE0) != 0)
-				irq |= INTVBL;
-		}
-	}
-}
--- a/sys/src/games/nes/ppu.c
+++ /dev/null
@@ -1,280 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include <mouse.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppuy, ppux, odd;
-
-static void
-pixel(int x, int y, int val, int back)
-{
-	union { u8int c[4]; u32int l; } u;
-	static u8int palred[64] = {
-		0x7C, 0x00, 0x00, 0x44, 0x94, 0xA8, 0xA8, 0x88, 
-		0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-		0xBC, 0x00, 0x00, 0x68, 0xD8, 0xE4, 0xF8, 0xE4, 
-		0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-		0xF8, 0x3C, 0x68, 0x98, 0xF8, 0xF8, 0xF8, 0xFC, 
-		0xF8, 0xB8, 0x58, 0x58, 0x00, 0x78, 0x00, 0x00, 
-		0xFC, 0xA4, 0xB8, 0xD8, 0xF8, 0xF8, 0xF0, 0xFC, 
-		0xF8, 0xD8, 0xB8, 0xB8, 0x00, 0xF8, 0x00, 0x00, 
-	};
-	static u8int palgreen[64] = {
-		0x7C, 0x00, 0x00, 0x28, 0x00, 0x00, 0x10, 0x14, 
-                0x30, 0x78, 0x68, 0x58, 0x40, 0x00, 0x00, 0x00, 
-                0xBC, 0x78, 0x58, 0x44, 0x00, 0x00, 0x38, 0x5C, 
-                0x7C, 0xB8, 0xA8, 0xA8, 0x88, 0x00, 0x00, 0x00, 
-                0xF8, 0xBC, 0x88, 0x78, 0x78, 0x58, 0x78, 0xA0, 
-                0xB8, 0xF8, 0xD8, 0xF8, 0xE8, 0x78, 0x00, 0x00, 
-                0xFC, 0xE4, 0xB8, 0xB8, 0xB8, 0xA4, 0xD0, 0xE0, 
-                0xD8, 0xF8, 0xF8, 0xF8, 0xFC, 0xD8, 0x00, 0x00, 
-	};
-	static u8int palblue[64] = {
-		0x7C, 0xFC, 0xBC, 0xBC, 0x84, 0x20, 0x00, 0x00, 
-                0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 
-                0xBC, 0xF8, 0xF8, 0xFC, 0xCC, 0x58, 0x00, 0x10, 
-                0x00, 0x00, 0x00, 0x44, 0x88, 0x00, 0x00, 0x00, 
-                0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0x98, 0x58, 0x44, 
-                0x00, 0x18, 0x54, 0x98, 0xD8, 0x78, 0x00, 0x00, 
-                0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xC0, 0xB0, 0xA8, 
-                0x78, 0x78, 0xB8, 0xD8, 0xFC, 0xF8, 0x00, 0x00, 
-	};
-
-	u.c[0] = palblue[val];
-	u.c[1] = palgreen[val];
-	u.c[2] = palred[val];
-	u.c[3] = back ? 0 : 0xFF;
-	*((u32int *)pic + y * 256 + x) = u.l;
-}
-
-static int
-iscolor(int x, int y)
-{
-	return pic[4 * (y * 256 + x) + 3] != 0;
-}
-
-static int
-pal(int c, int a, int spr)
-{
-	if(c == 0)
-		return ppuread(0x3F00);
-	return ppuread(0x3F00 | ((a&3)<<2) | (c & 3) | (spr << 4));
-}
-
-static void
-incppuy(void)
-{
-	int y;
-
-	if((ppuv & 0x7000) != 0x7000){
-		ppuv += 0x1000;
-		return;
-	}
-	y = (ppuv >> 5) & 31;
-	if(y++ == 29){
-		y = 0;
-		ppuv ^= 0x800;
-	}
-	ppuv = (ppuv & 0x0C1F) | ((y & 31) << 5);
-}
-
-static void
-drawbg(void)
-{
-	static int t;
-	u8int c, a;
-	static u8int nr1, nr2, na;
-	static u16int r1, r2, a1, a2;
-	
-	if(ppux >= 2 && ppux <= 257 || ppux >= 322 && ppux <= 337){
-		c = (r1 >> (15-ppusx)) & 1 | (r2 >> (14-ppusx)) & 2;
-		if(ppuy < 240 && ppux <= 257){
-			a = (a1 >> (15-ppusx)) & 1 | (a2 >> (14-ppusx)) & 2;
-			pixel(ppux-2, ppuy, pal(c, a, 0), c == 0);
-		}
-		r1 <<= 1;
-		r2 <<= 1;
-		a1 <<= 1;
-		a2 <<= 1;
-	}
-	if(ppux >= 256 && ppux <= 320){
-		if(ppux == 256)
-			incppuy();
-		if(ppux == 257)
-			ppuv = (ppuv & 0x7BE0) | (pput & 0x041F);
-		return;
-	}
-	switch(ppux & 7){
-	case 0:
-		if(ppux != 0){
-			if((ppuv & 0x1f) == 0x1f){
-				ppuv &= ~0x1f;
-				ppuv ^= 0x400;
-			}else
-				ppuv++;
-		}
-		break;
-	case 1:
-		t = ppuread(0x2000 | ppuv & 0x0FFF);
-		if(ppux != 1){
-			r1 |= nr1;
-			r2 |= nr2;
-			if(na & 1)
-				a1 |= 0xff;
-			if(na & 2)
-				a2 |= 0xff;
-		}
-		break;
-	case 3:
-		na = ppuread(0x23C0 | ppuv & 0x0C00 | ((ppuv & 0x0380) >> 4) | ((ppuv & 0x001C) >> 2));
-		if((ppuv & 0x0002) != 0) na >>= 2;
-		if((ppuv & 0x0040) != 0) na >>= 4;
-		break;
-	case 5:
-		nr1 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12);
-		break;
-	case 7:
-		nr2 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12 | 8);
-		break;
-	}
-}
-
-static void
-drawsprites(int show)
-{
-	uchar *p;
-	int big, dx, dy, i, x, cc, pri;
-	u8int r1, r2, c;
-	static int n, m, nz, s0, t0;
-	static struct { u8int x, a; u16int t; } s[8], *sp;
-	static struct { u8int x, a, r1, r2; } t[8];
-
-	big = (mem[PPUCTRL] & BIGSPRITE) != 0;
-	if(ppux == 65){
-		s0 = 0;
-		for(p = oam, sp = s, n = 0; p < oam + sizeof(oam); p += 4){
-			if((dy = p[0]) >= 0xEF)
-				continue;
-			dy = ppuy - dy;
-			if(dy < 0 || dy >= (big ? 16 : 8))
-				continue;
-			if(p == oam)
-				s0 = 1;
-			sp->t = p[1];
-			sp->a = p[2];
-			sp->x = p[3];
-			if((sp->a & (1<<7)) != 0)
-				dy = (big ? 15 : 7) - dy;
-			if(big){
-				sp->t |= (sp->t & 1) << 8;
-				if(dy >= 8){
-					sp->t |= 1;
-					dy -= 8;
-				}else
-					sp->t &= 0x1fe;
-			}else
-				sp->t |= (mem[PPUCTRL] & SPRTABLE) << 5;
-			sp->t = sp->t << 4 | dy;
-			sp++;
-			if(++n == 8)
-				break;
-		}
-	}
-	if(ppux >= 2 && ppux <= 257 && m > 0){
-		x = ppux - 2;
-		dx = x - t[0].x;
-		if(t0 && dx >= 0 && dx < 8 && ppux != 257){
-			if((nz & 1) != 0 && iscolor(x, ppuy) && show)
-				mem[PPUSTATUS] |= SPRITE0HIT;
-			nz >>= 1;
-		}
-		cc = -1;
-		pri = 0;
-		for(i = m - 1; i >= 0; i--){
-			dx = x - t[i].x;
-			if(dx < 0 || dx > 7)
-				continue;
-			c = (t[i].r1 & 1) | (t[i].r2 & 1) << 1;
-			if(c != 0){
-				cc = pal(c, t[i].a & 3, 1);
-				pri = (t[i].a & (1<<5)) == 0;
-			}
-			t[i].r1 >>= 1;
-			t[i].r2 >>= 1;
-		}
-		if(cc != -1 && show && (pri || !iscolor(x, ppuy)))
-			pixel(x, ppuy, cc, 0);
-	}
-	if(ppux == 257){
-		for(i = 0; i < n; i++){
-			r1 = ppuread(s[i].t);
-			r2 = ppuread(s[i].t | 8);
-			if((s[i].a & (1<<6)) == 0){
-				r1 = ((r1 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
-				r2 = ((r2 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
-			}
-			t[i].x = s[i].x;
-			t[i].a = s[i].a;
-			t[i].r1 = r1;
-			t[i].r2 = r2;
-		}
-		m = n;
-		nz = t[0].r1 | t[0].r2;
-		t0 = s0;
-	}
-}
-
-static void
-flush(void)
-{
-	flushmouse(1);
-	flushscreen();
-	flushaudio(audioout);
-}
-
-void
-ppustep(void)
-{
-	extern int nmi;
-	int mask;
-
-	if(ppuy < 240 || ppuy == 261){
-		mask = mem[PPUMASK];
-		if((mask & BGDISP) != 0)
-			drawbg();
-		if((((mask & BGDISP) == 0 && ppux <= 257 || ppux < 10 && (mask & BG8DISP) == 0) && ppux >= 2) && ppuy != 261)
-			pixel(ppux - 2, ppuy, ppuread(0x3F00), 1);
-		if((mask & SPRITEDISP) != 0 && ppuy != 261)
-			drawsprites(ppux >= 10 || (mask & SPRITE8DISP) != 0);
-		if(ppux == 240 && (mask & SPRITEDISP) != 0)
-			mapper[map](SCAN, 0);
-		if(ppuy == 261){
-			if(ppux == 1)
-				mem[PPUSTATUS] &= ~(PPUVBLANK|SPRITE0HIT);
-			else if(ppux >= 280 && ppux <= 304 && (mask & BGDISP) != 0)
-				ppuv = (pput & 0x7BE0) | (ppuv & 0x041F);
-		}
-	}else if(ppuy == 241){
-		if(ppux == 1){
-			mem[PPUSTATUS] |= PPUVBLANK;
-			if((mem[PPUCTRL] & PPUNMI) != 0)
-				nmi = 2;
-			flush();
-		}
-	}
-	ppux++;
-	if(ppux > 340){
-		ppux = 0;
-		ppuy++;
-		if(ppuy > 261){
-			ppuy = 0;
-			if(odd && (mem[PPUMASK] & (BGDISP | SPRITEDISP)) != 0)
-				ppux++;
-			odd ^= 1;
-		}
-	}
-}
--- a/sys/src/games/snes/ppu.c
+++ /dev/null
@@ -1,936 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppux, ppuy, rx;
-static u8int mode, bright, pixelpri[2], hires;
-static u32int pixelcol[2];
-u16int vtime = 0x1ff, htime = 0x1ff, subcolor;
-u16int hofs[5], vofs[5];
-s16int m7[6];
-
-enum {
-	M7A,
-	M7B,
-	M7C,
-	M7D,
-	M7X,
-	M7Y
-};
-
-enum { OBJ = 4, COL = 5, OBJNC = 8 };
-
-static u16int
-darken(u16int v)
-{
-	u8int r, g, b;
-	
-	r = (v >> 10) & 0x1f;
-	g = (v >> 5) & 0x1f;
-	b = v & 0x1f;
-	r = r * bright / 15;
-	g = g * bright / 15;
-	b = b * bright / 15;
-	return r << 10 | g << 5 | b;
-}
-
-static void
-pixeldraw(int x, int y, u16int v, int s)
-{
-	union { u16int w; u8int b[2]; } u;
-
-	if(bright != 0xf && s >= 0)
-		v = darken(v);
-	u.b[0] = v;
-	u.b[1] = v >> 8;
-	*((u16int *)pic + (x + y * 256)) = u.w;	/* FIXME: some weird shit in the diff */
-}
-
-static int
-window(int n)
-{
-	int a, w1, w2;
-
-	a = reg[0x2123 + (n >> 1)];
-	if((n & 1) != 0)
-		a >>= 4;
-	if((a & (WIN1|WIN2)) == 0)
-		return 0;
-	w1 = rx >= reg[0x2126] && rx <= reg[0x2127];
-	w2 = rx >= reg[0x2128] && rx <= reg[0x2129];
-	if((a & INVW1) != 0)
-		w1 = !w1;
-	if((a & INVW2) != 0)
-		w2 = !w2;
-	if((a & (WIN1|WIN2)) != (WIN1|WIN2))
-		return (a & WIN1) != 0 ? w1 : w2;
-	a = reg[0x212a + (n >> 2)] >> ((n & 3) << 1);
-	switch(a & 3){
-	case 1: return w1 & w2;
-	case 2: return w1 ^ w2;
-	case 3: return w1 ^ w2 ^ 1;
-	}
-	return w1 | w2;
-}
-
-static void
-npixel(int n, int v, int pri)
-{
-	int a;
-	
-	a = 1<<n;
-	if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
-		pixelcol[0] = v;
-		pixelpri[0] = pri;
-	}
-	if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
-		pixelcol[1] = v;
-		pixelpri[1] = pri;
-	}
-}
-
-static void
-spixel(int n, int v, int pri)
-{
-	int a;
-	
-	a = 1<<n;
-	if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
-		pixelcol[1] = v;
-		pixelpri[1] = pri;
-	}
-}
-
-static void
-mpixel(int n, int v, int pri)
-{
-	int a;
-	
-	a = 1<<n;
-	if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
-		pixelcol[0] = v;
-		pixelpri[0] = pri;
-	}
-}
-
-static void (*pixel)(int, int, int) = npixel;
-
-static u16int
-tile(int n, int tx, int ty)
-{
-	int a;
-	u16int ta;
-	u16int t;
-
-	a = reg[0x2107 + n];
-	ta = ((a & ~3) << 9) + ((tx & 0x1f) << 1) + ((ty & 0x1f) << 6);
-	if((a & 1) != 0)
-		ta += (tx & 0x20) << 6;
-	if((a & 2) != 0)
-		ta += (ty & 0x20) << (6 + (a & 1));
-	t = vram[ta++];
-	return t | vram[ta] << 8;
-}
-
-static void
-chr(int n, int nb, int w, int h, u16int t, int x, int y, u32int c[])
-{
-	u16int a;
-
-	if(w == 16)
-		t += (x >> 3 ^ t >> 14) & 1;
-	if(h == 16){
-		if(y >= 8){
-			t += (~t >> 11) & 16;
-			y -= 8;
-		}else
-			t += (t >> 11) & 16;
-	}
-	if((t & 0x8000) != 0)
-		y = 7 - y;
-	a = reg[0x210b + (n >> 1)];
-	if((n & 1) != 0)
-		a >>= 4;
-	else
-		a &= 0xf;
-	a = (a << 13) + (t & 0x3ff) * 8 * nb + y * 2;
-	c[0] = vram[a++];
-	c[0] |= vram[a] << 8;
-	if(nb != 2){
-		a += 15;
-		c[0] |= vram[a++] << 16;
-		c[0] |= vram[a] << 24;
-		if(nb == 8){
-			a += 15;
-			c[1] = vram[a++];
-			c[1] |= vram[a] << 8;
-			a += 15;
-			c[1] |= vram[a++] << 16;
-			c[1] |= vram[a] << 24;
-		}
-	}
-}
-
-static int
-palette(int n, int p)
-{
-	switch(mode){
-	case 0:
-		return p << 2 | n << 5;
-	case 1:
-		if(n >= 2)
-			return p << 2;
-	case 2:
-	case 6:
-		return p << 4;
-	case 5:
-		if(n == 0)
-			return p << 4;
-		return p << 2;
-	case 3:
-		if(n != 0)
-			return p << 4;
-	case 4:
-		if(n != 0)
-			return p << 2;
-		if((reg[CGWSEL] & DIRCOL) != 0)
-			return 0x10000;
-	}
-	return 0;
-}
-
-static void
-shift(u32int *c, int nb, int n, int d)
-{
-	if(d){
-		c[0] >>= n;
-		if(nb == 8)
-			c[1] >>= n;
-	}else{
-		c[0] <<= n;
-		if(nb == 8)
-			c[1] <<= n;
-	}
-}
-
-static u8int
-bgpixel(u32int *c, int nb, int d)
-{
-	u8int v;
-	
-	if(d){
-		v = c[0] & 1 | c[0] >> 7 & 2;
-		if(nb != 2){
-			v |= c[0] >> 14 & 4 | c[0] >> 21 & 8;
-			if(nb == 8){
-				v |= c[1] << 4 & 16 | c[1] >> 3 & 32 | c[1] >> 10 & 64 | c[1] >> 17 & 128;
-				c[1] >>= 1;
-			}
-		}
-		c[0] >>= 1;
-	}else{
-		v = c[0] >> 7 & 1 | c[0] >> 14 & 2;
-		if(nb != 2){
-			v |= c[0] >> 21 & 4 | c[0] >> 28 & 8;
-			if(nb == 8){
-				v |= c[1] >> 3 & 16 | c[1] >> 10 & 32 | c[1] >> 17 & 64 | c[1] >> 24 & 128;
-				c[1] <<= 1;
-			}
-		}
-		c[0] <<= 1;
-	}
-	return v;
-}
-
-static struct bgctxt {
-	u8int w, h, wsh, hsh, nb, pri[2];
-	u16int tx, ty, tnx, tny;
-	u16int t;
-	u32int c[2];
-	int pal;
-	u8int msz, mv, mx;
-	u16int otx, oty, otny;
-} bgctxts[4];
-
-static void
-bginit(int n, int nb, int prilo, int prihi)
-{
-	struct bgctxt *p;
-	int sx, sy;
-
-	p = bgctxts + n;
-	p->hsh = ((reg[BGMODE] & (1<<(4+n))) != 0) ? 4 : 3;
-	p->wsh = mode >= 5 ? 4 : p->hsh;
-	p->h = 1<<p->hsh;
-	p->w = 1<<p->wsh;
-	p->nb = nb;
-	p->pri[0] = prilo;
-	p->pri[1] = prihi;
-	sx = hofs[n];
-	sy = vofs[n] + ppuy;
-	if(reg[MOSAIC] != 0 && (reg[MOSAIC] & (1<<n)) != 0){
-		p->msz = (reg[MOSAIC] >> 4) + 1;
-		if(p->msz != 1){
-			sx -= p->mx = sx % p->msz;
-			sy -= sy % p->msz;
-		}
-	}else
-		p->msz = 1;
-	if(mode >= 5)
-		sx <<= 1;
-redo:
-	p->tx = sx >> p->wsh;
-	p->tnx = sx & (p->w - 1);
-	p->ty = sy >> p->hsh;
-	p->tny = sy & (p->h - 1);
-	p->t = tile(n, p->tx, p->ty);
-	chr(n, nb, p->w, p->h, p->t, p->tnx, p->tny, p->c);
-	p->pal = palette(n, p->t >> 10 & 7);
-	if((p->tnx & 7) != 0)
-		shift(p->c, nb, p->tnx & 7, p->t & 0x4000);
-	if(p->msz != 1 && p->mx != 0 && sx % p->msz == 0){
-		p->mv = bgpixel(p->c, nb, p->t & 0x4000);
-		if(p->tnx + p->mx >= 8){
-			sx += p->mx;
-			goto redo;
-		}else if(p->mx > 1)
-			shift(p->c, nb, p->mx - 1, p->t & 0x4000);
-	}
-
-}
-
-static void
-bg(int n)
-{
-	struct bgctxt *p;
-	u8int v;
-
-	p = bgctxts + n;
-	v = bgpixel(p->c, p->nb, p->t & 0x4000);
-	if(p->msz != 1)
-		if(p->mx++ == 0)
-			p->mv = v;
-		else{
-			if(p->mx == p->msz)
-				p->mx = 0;
-			v = p->mv;
-		}
-	if(v != 0)
-		pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
-	if(++p->tnx == p->w){
-		p->tx++;
-		p->tnx = 0;
-		p->t = tile(n, p->tx, p->ty);
-		p->pal = palette(n, p->t >> 10 & 7);
-	}
-	if((p->tnx & 7) == 0)
-		chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->tny, p->c);
-}
-
-static void
-optinit(void)
-{
-	struct bgctxt *p;
-	
-	p = bgctxts + 2;
-	p->hsh = (reg[BGMODE] & (1<<6)) != 0 ? 4 : 3;
-	p->wsh = mode >= 5 ? 4 : p->hsh;
-	p->w = 1<<p->wsh;
-	p->h = 1<<p->hsh;
-	p->tnx = hofs[2] & (p->w - 1);
-	p->tx = hofs[2] >> p->wsh;
-	bgctxts[0].otx = bgctxts[1].otx = 0xffff;
-	bgctxts[0].oty = bgctxts[0].ty;
-	bgctxts[0].otny = bgctxts[0].tny;
-	bgctxts[1].oty = bgctxts[1].ty;
-	bgctxts[1].otny = bgctxts[1].tny;
-}
-
-static void
-opt(void)
-{
-	struct bgctxt *p;
-	u16int hval, vval;
-	int sx, sy;
-	
-	p = bgctxts + 2;
-	if(++p->tnx == p->w){
-		if(mode == 4){
-			hval = tile(2, p->tx, vofs[2] >> p->hsh);
-			if((hval & 0x8000) != 0){
-				vval = hval;
-				hval = 0;
-			}else
-				vval = 0;
-		}else{
-			hval = tile(2, p->tx, vofs[2] >> p->hsh);
-			vval = tile(2, p->tx, (vofs[2]+8) >> p->hsh);
-		}
-		sx = (rx & ~7) + (hval & 0x1ff8);
-		sy = ppuy + (vval & 0x1fff);
-		if((vval & 0x2000) != 0){
-			bgctxts[0].oty = sy >> bgctxts[0].hsh;
-			bgctxts[0].otny = sy & (bgctxts[0].h - 1);
-		}else{
-			bgctxts[0].oty = bgctxts[0].ty;
-			bgctxts[0].otny = bgctxts[0].tny;
-		}
-		if((vval & 0x4000) != 0){
-			bgctxts[1].oty = sy >> bgctxts[1].hsh;
-			bgctxts[1].otny = sy & (bgctxts[1].h - 1);
-		}else{
-			bgctxts[1].oty = bgctxts[1].ty;
-			bgctxts[1].otny = bgctxts[1].tny;
-		}
-		if((hval & 0x2000) != 0)
-			bgctxts[0].otx = sx >> bgctxts[0].wsh;
-		else
-			bgctxts[0].otx = 0xffff;
-		if((hval & 0x4000) != 0)
-			bgctxts[1].otx = sx >> bgctxts[1].wsh;
-		else
-			bgctxts[1].otx = 0xffff;
-		p->tnx = 0;
-		p->tx++;
-	}
-}
-
-static void
-bgopt(int n)
-{
-	struct bgctxt *p;
-	u8int v;
-	
-	p = bgctxts + n;
-	v = bgpixel(p->c, p->nb, p->t & 0x4000);
-	if(p->msz != 1)
-		if(p->mx++ == 0)
-			p->mv = v;
-		else{
-			if(p->mx == p->msz)
-				p->mx = 0;
-			v = p->mv;
-		}
-	if(v != 0)
-		pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]);
-	if(++p->tnx == p->w){
-		p->tx++;
-		p->tnx = 0;
-	}
-	if((p->tnx & 7) == 0){
-		p->t = tile(n, p->otx == 0xffff ? p->tx : p->otx, p->oty);
-		p->pal = palette(n, p->t >> 10 & 7);
-		chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->otny, p->c);
-	}
-}
-
-struct bg7ctxt {
-	int x, y, x0, y0;
-	u8int msz, mx, mv;
-} b7[2];
-
-void
-calc7(void)
-{
-	s16int t;
-
-	if((reg[0x2105] & 7) != 7)
-		return;
-	t = hofs[4] - m7[M7X];
-	if((t & 0x2000) != 0)
-		t |= ~0x3ff;
-	else
-		t &= 0x3ff;
-	b7->x0 = (t * m7[M7A]) & ~63;
-	b7->y0 = (t * m7[M7C]) & ~63;
-	t = vofs[4] - m7[M7Y];
-	if((t & 0x2000) != 0)
-		t |= ~0x3ff;
-	else
-		t &= 0x3ff;
-	b7->x0 += (t * m7[M7B]) & ~63;
-	b7->y0 += (t * m7[M7D]) & ~63;
-	b7->x0 += m7[M7X] << 8;
-	b7->y0 += m7[M7Y] << 8;
-}
-
-static void
-bg7init(int n)
-{
-	u8int m, y;
-	struct bg7ctxt *p;
-	
-	p = b7 + n;
-	m = reg[M7SEL];
-	y = ppuy;
-	p->msz = 1;
-	if((reg[MOSAIC] & 1) != 0){
-		p->msz = (reg[MOSAIC] >> 4) + 1;
-		if(p->msz != 1)
-			y -= y % p->msz;
-	}
-	if(n == 1)
-		if((reg[MOSAIC] & 2) != 0)
-			p->msz = (reg[MOSAIC] >> 4) + 1;
-		else
-			p->msz = 1;
-	if((m & 2) != 0)
-		y = 255 - y;
-	p->x = b7->x0 + ((m7[M7B] * y) & ~63);
-	p->y = b7->y0 + ((m7[M7D] * y) & ~63);
-	if((m & 1) != 0){
-		p->x += 255 * m7[M7A];
-		p->y += 255 * m7[M7C];
-	}
-}
-
-static void
-bg7(int n)
-{
-	u16int x, y;
-	u8int m, v, t;
-	struct bg7ctxt *p;
-
-	p = b7 + n;
-	m = reg[M7SEL];
-	x = p->x >> 8;
-	y = p->y >> 8;
-	if((m & 0x80) == 0){
-		x &= 1023;
-		y &= 1023;
-	}else if(x > 1023 || y > 1023){
-		if((m & 0x40) != 0){
-			t = 0;
-			goto lookup;
-		}
-		v = 0;
-		goto end;
-	}
-	t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
-lookup:
-	v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
-end:
-	if(p->msz != 1){
-		if(p->mx == 0)
-			p->mv = v;
-		else
-			v = p->mv;
-		if(++p->mx == p->msz)
-			p->mx = 0;
-	}
-	if(n == 1){
-		if((v & 0x7f) != 0)
-			if((v & 0x80) != 0)
-				pixel(1, v & 0x7f, 0x71);
-			else
-				pixel(1, v, 0x11);
-	}else if(v != 0)
-		pixel(0, v, 0x40);
-	if((m & 1) != 0){
-		p->x -= m7[M7A];
-		p->y -= m7[M7C];
-	}else{
-		p->x += m7[M7A];
-		p->y += m7[M7C];
-	}
-}
-
-static void
-bgsinit(void)
-{
-	static int bitch[8];
-
-	pixel = npixel;
-	switch(mode){
-	case 0:
-		bginit(0, 2, 0x80, 0xb0);
-		bginit(1, 2, 0x71, 0xa1);
-		bginit(2, 2, 0x22, 0x52);
-		bginit(3, 2, 0x13, 0x43);
-		break;
-	case 1:
-		bginit(0, 4, 0x80, 0xb0);
-		bginit(1, 4, 0x71, 0xa1);
-		bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
-		break;
-	case 2:
-		bginit(0, 4, 0x40, 0xa0);
-		bginit(1, 4, 0x11, 0x71);
-		optinit();
-		break;
-	case 3:
-		bginit(0, 8, 0x40, 0xa0);
-		bginit(1, 4, 0x11, 0x71);
-		break;
-	case 4:
-		bginit(0, 8, 0x40, 0xa0);
-		bginit(1, 2, 0x11, 0x71);
-		optinit();
-		break;
-	case 5:
-		bginit(0, 4, 0x40, 0xa0);
-		bginit(1, 2, 0x11, 0x71);
-		break;
-	case 6:
-		bginit(0, 4, 0x40, 0xa0);
-		optinit();
-		break;
-	case 7:
-		bg7init(0);
-		if((reg[SETINI] & EXTBG) != 0)
-			bg7init(1);
-		break;
-	default:
-		bgctxts[0].w = bgctxts[1].w = 0;
-		if(bitch[mode]++ == 0)
-			print("bg mode %d not implemented\n", mode);
-	}
-}
-
-static void
-bgs(void)
-{
-	switch(mode){
-	case 0:
-		bg(0);
-		bg(1);
-		bg(2);
-		bg(3);
-		break;
-	case 1:
-		bg(0);
-		bg(1);
-		bg(2);
-		break;
-	case 2:
-	case 4:
-		opt();
-		bgopt(0);
-		bgopt(1);
-		break;
-	case 3:
-		bg(0);
-		bg(1);
-		break;
-	case 5:
-		pixel = spixel;
-		bg(0);
-		bg(1);
-		pixel = mpixel;
-		bg(0);
-		bg(1);
-		pixel = npixel;
-		break;
-	case 6:
-		opt();
-		pixel = spixel;
-		bgopt(0);
-		pixel = mpixel;
-		bgopt(0);
-		pixel = npixel;
-		break;
-	case 7:
-		bg7(0);
-		if((reg[SETINI] & EXTBG) != 0)
-			bg7(1);
-		break;
-	}
-}
-
-static void
-sprites(void)
-{
-	static struct {
-		short x;
-		u8int y, i, c, sx, sy;
-		u16int t0, t1;
-	} s[32], *sp;
-	static struct {
-		short x;
-		u8int sx, i, c, pal, pri;
-		u32int *ch;
-	} t[32], *tp;
-	static u32int ch[34];
-	static u8int *p, q;
-	static int n, m;
-	static int *sz;
-	static int szs[] = {
-		8, 8, 16, 16, 8, 8, 32, 32,
-		8, 8, 64, 64, 16, 16, 32, 32,
-		16, 16, 64, 64, 32, 32, 64, 64,
-		16, 32, 32, 64, 16, 32, 32, 32
-	};
-	static u16int base[2];
-	u8int dy, v, col, pri0, pri1, prio;
-	u16int a;
-	u32int w, *cp;
-	int i, nt, dx;
-
-	if(rx == 0){
-		n = 0;
-		sp = s;
-		sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
-		base[0] = (reg[OBSEL] & 0x07) << 14;
-		base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
-	}
-	if((rx & 1) == 0){
-		p = oam + 2 * rx;
-		if(p[1] == 0xf0)
-			goto nope;
-		q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
-		dy = ppuy - p[1];
-		sp->sx = sz[q & 2];
-		sp->sy = sz[(q & 2) + 1];
-		if(dy >= sp->sy)
-			goto nope;
-		sp->x = p[0];
-		if((q & 1) != 0)
-			sp->x |= 0xff00;
-		if(sp->x <= -(short)sp->sx && sp->x != -256)
-			goto nope;
-		if(n == 32){
-			reg[0x213e] |= 0x40;
-			goto nope;
-		}
-		sp->i = rx >> 1;
-		sp->y = p[1];
-		sp->c = p[3];
-		sp->t0 = p[2] << 5;
-		sp->t1 = base[sp->c & 1];
-		sp++;
-		n++;
-	}
-nope:
-	if(ppuy != 0){
-		col = 0;
-		pri0 = 0;
-		pri1 = 128;
-		if((reg[OAMADDH] & 0x80) != 0)
-			prio = oamaddr >> 2;
-		else
-			prio = 0;
-		for(i = 0, tp = t; i < m; i++, tp++){
-			dx = rx - tp->x;
-			if(dx < 0 || dx >= tp->sx)
-				continue;
-			w = *tp->ch;
-			if((tp->c & 0x40) != 0){
-				v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
-				*tp->ch = w >> 1;
-			}else{
-				v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
-				*tp->ch = w << 1;
-			}
-			if((dx & 7) == 7)
-				tp->ch++;
-			nt = (tp->i - prio) & 0x7f;
-			if(v != 0 && nt < pri1){
-				col = tp->pal + v;
-				pri0 = tp->pri;
-				pri1 = nt;
-			}
-		}
-		if(col > 0)
-			pixel(OBJ, col, pri0);
-	}
-	if(rx == 255){
-		cp = ch;
-		m = n;
-		for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
-			tp->x = sp->x;
-			tp->sx = 0;
-			tp->c = sp->c;
-			tp->pal = 0x80 | sp->c << 3 & 0x70;
-			tp->pri = 3 * (0x10 + (sp->c & 0x30));
-			if((tp->c & 8) != 0)
-				tp->pri |= OBJ;
-			else
-				tp->pri |= OBJNC;
-			tp->ch = cp;
-			tp->i = sp->i;
-			nt = sp->sx >> 3;
-			dy = ppuy - sp->y;
-			if((sp->c & 0x80) != 0)
-				dy = sp->sy - 1 - dy;
-			a = sp->t0 | (dy & 7) << 1;
-			if(dy >= 8)
-				a += (dy & ~7) << 6;
-			if(sp->x < 0 && (i = (-sp->x >> 3)) != 0){
-				if((sp->c & 0x40) != 0)
-					a -= i << 5;
-				else
-					a += i << 5;
-				nt -= i;
-				tp->sx += i << 3;
-			}
-			if((sp->c & 0x40) != 0){
-				a += sp->sx * 4;
-				for(i = 0; i < nt; i++){
-					if(cp < ch + nelem(ch)){
-						w  = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
-						w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
-						w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
-						w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
-						*cp++ = w;
-						tp->sx += 8;
-					}else
-						reg[0x213e] |= 0x80;
-				}
-			}else
-				for(i = 0; i < nt; i++){
-					if(cp < ch + nelem(ch)){
-						w  = vram[sp->t1 | a & 0x1fff];
-						w |= vram[sp->t1 | ++a & 0x1fff] << 8;
-						w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
-						w |= vram[sp->t1 | ++a & 0x1fff] << 24;
-						*cp++ = w;
-						tp->sx += 8;
-						a += 15;
-					}else
-						reg[0x213e] |= 0x80;
-				}
-			if(sp->x < 0 && (i = (-sp->x) & 7) != 0)
-				if((sp->c & 0x40) != 0)
-					*tp->ch >>= i;
-				else
-					*tp->ch <<= i;
-		}
-	}
-}
-
-static u16int
-colormath(int n)
-{
-	u16int v, w, r, g, b;
-	u8int m, m2, div;
-	int cw;
-	
-	m = reg[CGWSEL];
-	m2 = reg[CGADSUB];
-	cw = -1;
-	switch(m >> 6){
-	default: v = 1; break;
-	case 1: v = cw = window(COL); break;
-	case 2: v = !(cw = window(COL)); break;
-	case 3: v = 0; break;
-	}
-	if(v){
-		if((pixelcol[n] & 0x10000) != 0)
-			v = pixelcol[n];
-		else
-			v = cgram[pixelcol[n] & 0xff];
-	}
-	if((m2 & (1 << (pixelpri[n] & 0xf))) == 0)
-		return v;
-	switch((m >> 4) & 3){
-	case 0: break;
-	case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
-	case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
-	default: return v;
-	}
-	div = (m2 & 0x40) != 0;
-	if((m & 2) != 0){
-		if((pixelcol[1-n] & 0x10000) != 0)
-			w = pixelcol[1-n];
-		else
-			w = cgram[pixelcol[1-n] & 0xff];
-		div = div && (pixelpri[1-n] & 0xf) != COL;
-	}else
-		w = subcolor;
-	if((m2 & 0x80) != 0){
-		r = (v & 0x7c00) - (w & 0x7c00);
-		g = (v & 0x03e0) - (w & 0x03e0);
-		b = (v & 0x001f) - (w & 0x001f);
-		if(r > 0x7c00) r = 0;
-		if(g > 0x03e0) g = 0;
-		if(b > 0x001f) b = 0;
-		if(div){
-			r = (r >> 1) & 0xfc00;
-			g = (g >> 1) & 0xffe0;
-			b >>= 1;
-		}
-		return r | g | b;
-	}else{
-		r = (v & 0x7c00) + (w & 0x7c00);
-		g = (v & 0x03e0) + (w & 0x03e0);
-		b = (v & 0x001f) + (w & 0x001f);
-		if(div){
-			r = (r >> 1) & 0xfc00;
-			g = (g >> 1) & 0xffe0;
-			b >>= 1;
-		}
-		if(r > 0x7c00) r = 0x7c00;
-		if(g > 0x03e0) g = 0x03e0;
-		if(b > 0x001f) b = 0x001f;
-		return r | g | b;
-	}
-}
-
-void
-ppustep(void)
-{
-	int yvbl;
-
-	mode = reg[BGMODE] & 7;
-	bright = reg[INIDISP] & 0xf;
-	hires = mode >= 5 && mode < 7 || (reg[SETINI] & 8) != 0;
-	yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1;
-
-	if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){
-		rx = ppux - XLEFT;
-		if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
-			pixelcol[0] = 0;
-			pixelpri[0] = COL;
-			pixelcol[1] = 0x10000 | subcolor;
-			pixelpri[1] = COL;	
-			bgs();
-			sprites();
-			if(ppuy != 0)
-				if(hires){
-					pixeldraw(rx, ppuy - 1, colormath(1), 0);
-					pixeldraw(rx, ppuy - 1, colormath(0), 1);
-				}else
-					pixeldraw(rx, ppuy - 1, colormath(0), 0);
-		}else if(ppuy != 0)
-			pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x6739 : 0, -1);
-	}
-
-	if(ppux == 134)
-		cpupause = 1;
-	if(ppux == 0x116 && ppuy <= yvbl)
-		hdma |= reg[0x420c];
-	if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime+4 == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy))
-		irq |= IRQPPU;
-	if(++ppux >= 340){
-		ppux = 0;
-		if(++ppuy >= 262){
-			ppuy = 0;
-			reg[RDNMI] &= ~VBLANK;
-			reg[0x213e] = 1;
-			reg[0x213f] ^= 0x80;
-			hdma = reg[0x420c]<<8;
-			flush();
-		}
-		if(ppuy < yvbl)
-			bgsinit();
-		if(ppuy == yvbl){
-			reg[RDNMI] |= VBLANK;
-			if((reg[NMITIMEN] & VBLANK) != 0)
-				nmi = 2;
-			if((reg[INIDISP] & 0x80) == 0)
-				oamaddr = reg[0x2102] << 1 | (reg[0x2103] & 1) << 9;
-			if((reg[NMITIMEN] & AUTOJOY) != 0){
-				memwrite(0x4016, 1);
-				memwrite(0x4016, 0);
-				reg[0x4218] = keylatch >> 16;
-				reg[0x4219] = keylatch >> 24;
-				keylatch = keylatch << 16 | 0xffff;
-			}
-		}
-		if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)
-			irq |= IRQPPU;
-	}
-}
--