shithub: riscv

Download patch

ref: edfdc4ac07fe2748b72d36ea455876907227c4c3
parent: 0b001e265cac185947c0b0c919dbab6afec2f72c
author: aiju <devnull@localhost>
date: Wed Apr 1 12:17:17 EDT 2015

new games/gb: better emulation and gbc support

--- /dev/null
+++ b/sys/src/games/gb/apu.c
@@ -1,0 +1,382 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+Event evsamp, evenv;
+s16int sbuf[2*4000], *sbufp;
+enum {
+	Freq = 44100,
+	SRATEDIV = 8388608 / Freq,
+	ENVDIV = 8388608 / 512
+};
+static int fd;
+
+u16int envmod;
+u8int sweepen, sweepctr;
+u16int sweepfreq;
+typedef struct chan chan;
+struct chan {
+	u8int n, ectr;
+	u16int len;
+	u8int *env, *freq;
+	u16int fctr, fthr;
+	u32int finc;
+	u8int vol;
+};
+u8int wave[32];
+u8int wpos;
+u16int lfsr;
+
+chan sndch[4] = {
+	{
+		.n = 0,
+		.env = reg + NR12,
+		.freq = reg + NR14,
+	},
+	{
+		.n = 1,
+		.env = reg + NR22,
+		.freq = reg + NR24,
+	},
+	{
+		.n = 2,
+	},
+	{
+		.n = 3,
+		.env = reg + NR42,
+		.freq = reg + NR44,
+	}
+};
+
+Var apuvars[] = {
+	VAR(envmod), VAR(sweepen),
+	VAR(sweepctr), VAR(sweepfreq), ARR(wave), VAR(wpos), 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 / (Freq * (2048 - (v & 0x7ff)));
+		break;
+	case 2:
+		sndch[2].finc = 2097152ULL * 65536 / (Freq * (2048 - (v & 0x7ff)));
+		break;
+	case 3:
+		sndch[3].finc = 524288ULL * 65536 / Freq;
+		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<<6) != 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 & 7;
+	if((*c->env & 1<<3) != 0){
+		if(c->vol < 15)
+			c->vol++;
+	}else
+		if(c->vol > 0)
+			c->vol--;
+}
+
+s8int
+wavesamp(void)
+{
+	s8int x;
+	int v;
+
+	sndch[2].fctr = v = sndch[2].fctr + sndch[2].finc;
+	if(sndch[2].len == 0 || (reg[NR30] & 1<<7) == 0)
+		return 0;
+	for(;;){
+		x = wave[wpos];
+		v -= 0x10000;
+		if(v < 0)
+			break;
+		wpos = wpos + 1 & 31;
+	}
+	if((reg[NR32] & 3<<5) == 0)
+		x = 0;
+	else
+		x = x >> (reg[NR32] >> 5 & 3) - 1;
+	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[NR10];
+	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[NR13] = fr;
+		reg[NR14] = reg[NR14] & 0xf8 | fr >> 8;
+		rate(0, fr);
+		sweep(0);
+	}
+}
+
+void
+sndstart(chan *c, u16int v)
+{
+	u8int cnt;
+
+	c->vol = *c->env >> 4;
+	c->ectr = *c->env & 7;
+	if(c->len == 0)
+		c->len = 64;
+	if(c == sndch){
+		cnt = reg[NR10];
+		sweepen = (cnt & 0x07) != 0 && (cnt & 0x70) != 0;
+		sweepctr = cnt >> 4 & 7;
+		sweepfreq = v & 0x7ff;
+		if((cnt & 0x07) != 0)
+			sweep(0);
+	}
+}
+
+void
+envtick(void *)
+{
+	addevent(&evenv, ENVDIV);
+
+	env(&sndch[0]);
+	env(&sndch[1]);
+	if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[NR34] & 0x40) != 0)
+		sndch[2].len--;
+	env(&sndch[3]);
+	if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
+		sweepctr = reg[NR10] >> 4 & 7;
+		sweep(1);
+	}
+	envmod++;
+}
+
+void
+sampletick(void *)
+{
+	u8int cntl, cnth;
+	s16int ch[4];
+	s16int s[2];
+	int i;
+	
+	addevent(&evsamp, SRATEDIV);
+	
+	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[NR50];
+	cnth = reg[NR51];
+	s[0] = 0;
+	s[1] = 0;
+	for(i = 0; i < 4; i++){
+		if((cnth & 1<<i) != 0)
+			s[1] += ch[i] * (1 + (cntl & 7));
+		if((cnth & 1<<4<<i) != 0)
+			s[0] += ch[i] * (1 + (cntl >> 4 & 7));
+	}
+	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;
+	
+	if(sbufp < sbuf + nelem(sbuf)){
+		sbufp[0] = s[0] << 6;
+		sbufp[1] = s[1] << 6;
+		sbufp += 2;
+	}
+}
+
+void
+sndwrite(u8int a, u8int v)
+{
+	static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
+	
+	if((reg[NR52] & 0x80) == 0 && a != NR52)
+		return;
+	switch(a){
+	case NR11:
+		sndch[0].fthr = thr[v >> 6 & 3];
+		sndch[0].len = 64 - (v & 63);
+		break;
+	case NR13:
+		rate(0, reg[NR14] << 8 & 0x700 | v);
+		break;
+	case NR14:
+		rate(0, v << 8 & 0x700 | reg[NR13]);
+		if((v & 1<<7) != 0)
+			sndstart(&sndch[0], v);
+		break;
+	case NR21:
+		sndch[1].fthr = thr[v >> 6 & 3];
+		break;
+	case NR23:
+		rate(1, reg[NR24] << 8 & 0x700 | v);
+		break;
+	case NR24:
+		rate(1, v << 8 & 0x700 | reg[NR23]);
+		if((v & 1<<7) != 0)
+			sndstart(&sndch[1], v);
+		break;
+	case NR30:
+		if((v & 1<<7) != 0 && sndch[2].len == 0)
+			sndch[2].len = 256;
+		break;
+	case NR31:
+		sndch[2].len = 256 - (v & 0xff);
+		break;
+	case NR33:
+		rate(2, reg[NR34] << 8 & 0x700 | v);
+		break;
+	case NR34:
+		rate(2, v << 8 & 0x700 | reg[NR33]);
+		break;
+	case NR43:
+		rate(3, v);
+		break;
+	case NR44:
+		if((v & 1<<7) != 0){
+			if((reg[NR43] & 1<<3) != 0)
+				lfsr = 0x7f;
+			else
+				lfsr = 0x7fff;
+			sndstart(&sndch[3], v);
+		}
+		break;
+	case NR52:
+		if((v & 0x80) == 0){
+			memset(reg + NR10, 0, NR52 - NR10);
+			sndch[0].len = 0;
+			sndch[1].len = 0;
+			sndch[2].len = 0;
+			sndch[3].len = 0;
+		}
+	}
+}
+
+int
+apuread(void)
+{
+	u8int v;
+	
+	v = reg[NR52] & 0xf0;
+	if(sndch[0].len != 0) v |= 1;
+	if(sndch[1].len != 0) v |= 2;
+	if(sndch[2].len != 0) v |= 4;
+	if(sndch[3].len != 0) v |= 8;
+	return v;
+}
+
+u8int
+waveread(u8int a)
+{
+	a <<= 1;
+	return wave[a + wpos & 31] << 4 | wave[a + wpos + 1 & 31];
+}
+
+void
+wavewrite(u8int a, u8int v)
+{
+	a <<= 1;
+	wave[a + wpos & 31] = v >> 4;
+	wave[a + wpos + 1 & 31] = v & 0x0f;
+}
+
+void
+audioinit(void)
+{
+	fd = open("/dev/audio", OWRITE);
+	if(fd < 0)
+		sysfatal("open: %r");
+	sbufp = sbuf;
+	evsamp.f = sampletick;
+	addevent(&evsamp, SRATEDIV);
+	evenv.f = envtick;
+	addevent(&evenv, ENVDIV);
+}
+
+int
+audioout(void)
+{
+	int rc;
+	static int cl;
+
+	if(sbufp == nil)
+		return -1;
+	if(sbufp == sbuf)
+		return 0;
+	cl = clock;
+	rc = write(fd, sbuf, (sbufp - sbuf) * 2);
+	if(rc > 0)
+		sbufp -= (rc+1)/2;
+	if(sbufp < sbuf)
+		sbufp = sbuf;
+	return 0;
+}
--- a/sys/src/games/gb/audio.c
+++ /dev/null
@@ -1,231 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include "dat.h"
-#include "fns.h"
-
-static int fd;
-static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v;
-extern int paused;
-
-static short sbuf[2*2000], *sbufp;
-
-static int
-thresh(int f, int b)
-{
-	switch(b){
-	case 0: return f/8;
-	case 1: return f/4;
-	case 2: return f/2;
-	default: return 3*f/4;
-	}
-}
-
-static int
-freq(int lower)
-{
-	int f;
-	
-	f = mem[lower+1] & 7;
-	f = (f << 8) | mem[lower];
-	f = muldiv(2048 - f, SAMPLE, 131072);
-	return f;
-}
-
-static void
-soundlen(int len, int ctrl, int n)
-{
-	if(mem[ctrl] & 128){
-		mem[0xFF26] |= (1<<n);
-		mem[ctrl] &= ~128;
-		switch(n){
-		case 0:
-			ch1v = mem[0xFF12];
-			break;
-		case 1:
-			ch2v = mem[0xFF17];
-			break;
-		case 3:
-			ch4v = mem[0xFF21];
-			break;
-		}
-	}
-	if((mem[ctrl] & 64) == 0){
-		mem[0xFF26] |= (1<<n);
-		return;
-	}
-	if((mem[0xFF26] & (1<<n)) == 0)
-		return;
-	if(mem[len] == ((n == 2) ? 255 : 63)){
-		mem[0xFF26] &= ~(1<<n);
-		return;
-	}
-	mem[len]++;
-}
-
-static void
-envelope(int *v, int *c)
-{
-	int f;
-	
-	f = (*v & 7) * SAMPLE / 64;
-	if(f == 0)
-		return;
-	if(*c >= f){
-		if(*v & 8){
-			if((*v >> 4) < 0xF)
-				*v += 0x10;
-		}else
-			if((*v >> 4) > 0)
-				*v -= 0x10;
-		*c = 0;
-	}
-	(*c)++;
-}
-
-void
-audiosample(void)
-{
-	int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s;
-	u8int f;
-	
-	if(sbufp == nil)
-		return;
-	if(sc >= SAMPLE/256){
-		soundlen(0xFF11, 0xFF14, 0);
-		soundlen(0xFF16, 0xFF19, 1);
-		soundlen(0xFF1B, 0xFF1E, 2);
-		soundlen(0xFF20, 0xFF23, 3);
-		sc = 0;
-	}
-	sc++;
-	envelope(&ch1v, &ch1vec);
-	envelope(&ch2v, &ch2vec);
-	envelope(&ch4v, &ch4vec);
-
-	ch1f = freq(0xFF13);
-	if(ch1c >= ch1f)
-		ch1c = 0;
-	if(ch1c >= thresh(ch1f, mem[0xFF11] >> 6))
-		ch1s = 1;
-	else
-		ch1s = -1;
-	ch1s *= ch1v >> 4;
-	ch1s *= 8000 / 0xF;
-	ch1c++;
-
-	ch2f = freq(0xFF18);
-	if(ch2c >= ch2f)
-		ch2c = 0;
-	if(ch2c >= thresh(ch1f, mem[0xFF16] >> 6))
-		ch2s = 1;
-	else
-		ch2s = -1;
-	ch2s *= ch2v >> 4;
-	ch2s *= 8000 / 0xF;
-	ch2c++;
-	
-	ch3f = freq(0xFF1D) * 100 / 32;
-	if(ch3f == 0)
-		ch3f = 1;
-	ch3s = 0;
-	if(mem[0xFF1A] & 0x80){
-		if(ch3c >= freq(0xFF1D))
-			ch3c = 0;
-		k = ch3c * 100 / ch3f;
-		ch3s = mem[0xFF30 + (k >> 1)];
-		if(k & 1)
-			ch3s &= 0xF;
-		else
-			ch3s >>= 4;
-		switch(mem[0xFF1C]){
-		case 0:
-			ch3s = 0;
-			break;
-		case 2:
-			ch3s >>= 1;
-			break;
-		case 3:
-			ch3s >>= 2;
-			break;
-		}
-		ch3s *= 8000 / 0xF;
-		ch3c++;	
-	}
-	
-	r = mem[0xFF22] & 7;
-	s = mem[0xFF22] >> 4;
-	if(r != 0)
-		ch4f = 524288 / r;
-	else
-		ch4f = 524288 * 2;
-	ch4f >>= s+1;
-	if(ch4f == 0)
-		ch4f = 1;
-	ch4f = SAMPLE / ch4f;
-	if(ch4c >= ch4f){
-		ch4sr <<= 1;
-		if(mem[0xFF22] & 4)
-			k = ((ch4sr >> 6) ^ (ch4sr >> 7)) & 1;
-		else
-			k = ((ch4sr >> 14) ^ (ch4sr >> 15)) & 1;
-		ch4sr |= k;
-		ch4c = 0;
-	}
-	ch4c++;
-	if(ch4sr & 1)
-		ch4s = -1;
-	else
-		ch4s = 1;
-	ch4s *= ch4v >> 4;
-	ch4s *= 8000 / 0xF;
-	
-	f = mem[0xFF25];
-	r = mem[0xFF26] & 15;
-	r = r | (r << 4);
-	f &= r;
-	if(sbufp < sbuf + nelem(sbuf) - 1){
-		*sbufp = 0;
-		if(f & 0x01) *sbufp += ch1s;
-		if(f & 0x02) *sbufp += ch2s;
-		if(f & 0x04) *sbufp += ch3s;
-		if(f & 0x08) *sbufp += ch4s;
-		*++sbufp = 0;
-		if(f & 0x10) *sbufp += ch1s;
-		if(f & 0x20) *sbufp += ch2s;
-		if(f & 0x40) *sbufp += ch3s;
-		if(f & 0x80) *sbufp += ch4s;
-		sbufp++;
-	}
-}
-
-int
-audioout(void)
-{
-	int rc;
-
-	if(sbufp == nil)
-		return -1;
-	if(sbufp == sbuf)
-		return 0;
-	rc = write(fd, sbuf, (sbufp - sbuf) * 2);
-	if(rc > 0)
-		sbufp -= (rc+1)/2;
-	if(sbufp < sbuf)
-		sbufp = sbuf;
-	return 0;
-}
-
-void
-initaudio(void)
-{
-	mem[0xFF26] = 0xF;
-	ch1v = 0xF0;
-	ch2v = 0xF0;
-	ch4v = 0xF0;
-	fd = open("/dev/audio", OWRITE);
-	if(fd < 0)
-		return;
-	sbufp = sbuf;
-}
--- a/sys/src/games/gb/cpu.c
+++ b/sys/src/games/gb/cpu.c
@@ -1,21 +1,25 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
-#include <draw.h>
 #include "dat.h"
 #include "fns.h"
 
-#define lohi(L, H) (((u16int)L) | (((u16int)H) << 8))
+u8int r[8], ime;
+u16int pc, curpc, sp;
+int halt, trace;
 
-u8int R[8], Fl;
-u16int pc, sp, curpc;
-int halt, IME;
+enum {
+	FLAGC = 0x10,
+	FLAGH = 0x20,
+	FLAGN = 0x40,
+	FLAGZ = 0x80
+};
+enum { rB, rC, rD, rE, rH, rL, rHL, rA, rF = rHL };
+#define BC() (r[rB] << 8 | r[rC])
+#define DE() (r[rD] << 8 | r[rE])
+#define HL() (r[rH] << 8 | r[rL])
 
-static void
-invalid(void)
-{
-	sysfatal("invalid instruction %.2x (pc = %.4x)", memread(curpc), curpc);
-}
+Var cpuvars[] = { ARR(r), VAR(ime), VAR(pc), VAR(curpc), VAR(sp), VAR(halt), {nil, 0, 0} };
 
 static u8int
 fetch8(void)
@@ -26,24 +30,23 @@
 static u16int
 fetch16(void)
 {
-	u16int r;
+	u16int u;
 	
-	r = lohi(memread(pc), memread(pc+1));
-	pc += 2;
-	return r;
+	u = memread(pc++);
+	return u | memread(pc++) << 8;
 }
 
 static void
-push8(u8int n)
+push8(u8int u)
 {
-	memwrite(--sp, n);
+	memwrite(--sp, u);
 }
 
 static void
-push16(u16int n)
+push16(u16int u)
 {
-	memwrite(--sp, n >> 8);
-	memwrite(--sp, n);
+	memwrite(--sp, u >> 8);
+	memwrite(--sp, u);
 }
 
 static u8int
@@ -55,792 +58,497 @@
 static u16int
 pop16(void)
 {
-	u8int a, b;
+	u16int v;
 	
-	b = pop8();
-	a = pop8();
-	return lohi(b, a);
+	v = memread(sp++);
+	return v | memread(sp++) << 8;
 }
 
-static int
-ld01(u8int op)
+static u16int
+read16(u16int n)
 {
-	u8int val, a, b;
-	int time;
-	
-	a = (op & 0x38) >> 3;
-	b = op & 7;
-	time = 4;
-	if(a == rHL && b == rHL){
-		halt = 1;
-		return 4;
-	}
-	if(b == rHL){
-		val = memread(lohi(R[rL], R[rH]));
-		time = 8;
-	}else{
-		val = R[b];
-	}
-	if(a == rHL){
-		memwrite(lohi(R[rL], R[rH]), val);
-		time = 8;
-	}else{
-		R[a] = val;
-	}
-	return time;
+	return memread(n) | memread(n+1) << 8;
 }
 
-static int
-ldi(u8int op)
+static void
+write16(u16int n, u16int v)
 {
-	u8int val, a;
-	
-	val = fetch8();
-	a = (op & 0x38) >> 3;
-	if(a == rHL){
-		memwrite(lohi(R[rL], R[rH]), val);
-		return 12;
-	}else{
-		R[a] = val;
-		return 8;
-	}
+	memwrite(n++, v);
+	memwrite(n, v >> 8);
 }
 
 static int
-ld16(u8int op)
+move(u8int dst, u8int src)
 {
-	u16int val;
-	u8int a;
-	
-	val = fetch16();
-	a = (op & 0x30) >> 4;
-	switch(a){
-	case 0:
-		R[rB] = val >> 8;
-		R[rC] = val;
-		break;
-	case 1:
-		R[rD] = val >> 8;
-		R[rE] = val;
-		break;
-	case 2:
-		R[rH] = val >> 8;
-		R[rL] = val;
-		break;
-	case 3:
-		sp = val;
-		break;
+	if(dst == rHL){
+		if(src == rHL){
+			halt = 1;
+			return 4;
+		}
+		memwrite(HL(), r[src]);
+		return 8;
 	}
-	return 12;
-}
-
-static int
-add16(u8int op)
-{
-	u16int val1, val2;
-	u8int a;
-	u32int val32;
-	
-	a = (op & 0x30) >> 4;
-	switch(a){
-	case 0:
-		val1 = lohi(R[rC], R[rB]);
-		break;
-	case 1:
-		val1 = lohi(R[rE], R[rD]);
-		break;
-	case 2:
-		val1 = lohi(R[rL], R[rH]);
-		break;
-	default:
-		val1 = sp;
+	if(src == rHL){
+		r[dst] = memread(HL());
+		return 8;
 	}
-	Fl &= FLAGZ;
-	val2 = lohi(R[rL], R[rH]);
-	val32 = (u32int)(val1) + (u32int)(val2);
-	if(val32 > 0xFFFF)
-		Fl |= FLAGC;
-	if(((val1&0xFFF)+(val2&0xFFF)) > 0xFFF)
-		Fl |= FLAGH;
-	R[rL] = val32;
-	R[rH] = val32 >> 8;
-	return 8;
+	r[dst] = r[src];
+	return 4;
 }
 
 static int
-ldin(u8int op)
+alu(u8int op, u8int n)
 {
-	u16int addr;
+	u8int v4;
+	u8int u;
+	u16int v;
+	int t;
 
-	switch(op >> 4){
-	case 0:
-		addr = lohi(R[rC], R[rB]);
+	switch(n){
+	case 8: u = fetch8(); t = 8; break;
+	case rHL:
+		u = memread(HL());
+		t = 8;
 		break;
-	case 1:
-		addr = lohi(R[rE], R[rD]);
-		break;
 	default:
-		addr = lohi(R[rL], R[rH]);
+		u = r[n];
+		t = 4;
 	}
-	if(op & 8){
-		R[rA] = memread(addr);
-	}else{
-		memwrite(addr, R[rA]);
-	}
-	if((op >> 4) > 1){
-		if(op & 16)
-			addr--;
-		else
-			addr++;
-		R[rL] = addr;
-		R[rH] = addr >> 8;
-	}
-	return 8;
-}
-
-static int
-inc16(u8int op)
-{
-	u16int val;
-	u8int a;
-	
-	a = (op & 0x38) >> 3;
-	switch(a >> 1){
-	case 0:
-		val = lohi(R[rC], R[rB]);
-		break;
-	case 1:
-		val = lohi(R[rE], R[rD]);
-		break;
-	case 2:
-		val = lohi(R[rL], R[rH]);
-		break;
+	v4 = 0;
+	switch(op){
 	default:
-		val = sp;
-	}
-	if(a & 1)
-		val--;
-	else
-		val++;
-	switch(a >> 1){
-	case 0:
-		R[rB] = val >> 8;
-		R[rC] = val;
+		v4 = (r[rA] & 0x0f) + (u & 0x0f);
+		v = r[rA] + u;
 		break;
 	case 1:
-		R[rD] = val >> 8;
-		R[rE] = val;
+		v4 = (r[rA] & 0x0f) + (u & 0x0f) + (r[rF] >> 4 & 1);
+		v = r[rA] + u + (r[rF] >> 4 & 1);
 		break;
 	case 2:
-		R[rH] = val >> 8;
-		R[rL] = val;
+	case 7:
+		v4 = (r[rA] & 0x0f) + (~u & 0x0f) + 1;
+		v = r[rA] + (u ^ 0xff) + 1;
 		break;
-	default:
-		sp = val;
+	case 3:
+		v4 = (r[rA] & 0x0f) + (~u & 0x0f) + (~r[rF] >> 4 & 1);
+		v = r[rA] + (u ^ 0xff) + (~r[rF] >> 4 & 1);
+		break;
+	case 4: v = r[rA] & u; break;
+	case 5: v = r[rA] ^ u; break;
+	case 6: v = r[rA] | u; break;
 	}
-	return 8;
+	r[rF] = 0;
+	if((u8int)v == 0)
+		r[rF] |= FLAGZ;
+	if(op < 2){
+		if((v & 0x100) != 0)
+			r[rF] |= FLAGC;
+		if((v4 & 0x10) != 0)
+			r[rF] |= FLAGH;
+	}else if(op < 4 || op == 7){
+		r[rF] |= FLAGN;
+		if((v & 0x100) == 0)
+			r[rF] |= FLAGC;
+		if((v4 & 0x10) == 0)
+			r[rF] |= FLAGH;
+	}else
+		if(op == 4)
+			r[rF] |= FLAGH;
+	if(op != 7)
+		r[rA] = v;
+	return t;
 }
 
 static int
-inc8(u8int op)
+branch(int cc, int t)
 {
-	u8int val, a;
-	int time;
+	u16int v;
 	
-	a = (op & 0x38) >> 3;
-	if(a == rHL){
-		val = memread(lohi(R[rL], R[rH]));
-		time = 12;
-	}else{
-		val = R[a];
-		time = 4;
-	}
-	if(a == rHL){
-		memwrite(lohi(R[rL], R[rH]), val+1);
-	}else{
-		R[a] = val + 1;
-	}
-	Fl &= FLAGC;
-	if(val == 0xFF)
-		Fl |= FLAGZ;
-	if((val & 0xF) == 0xF)
-		Fl |= FLAGH;
-	return time;
+	v = (s8int)fetch8();
+	if(!cc)
+		return t + 8;
+	pc += v;
+	return t + 12;
 }
 
-static int
-dec8(u8int op)
+static u8int
+inc(u8int v)
 {
-	u8int val, a;
-	int time;
-	
-	a = (op & 0x38) >> 3;
-	if(a == rHL){
-		val = memread(lohi(R[rL], R[rH]));
-		time = 12;
-	}else{
-		val = R[a];
-		time = 4;
-	}
-	if(a == rHL){
-		memwrite(lohi(R[rL], R[rH]), val - 1);
-	}else{
-		R[a] = val - 1;
-	}
-	Fl = (Fl & FLAGC) | FLAGN;
-	if(val == 1)
-		Fl |= FLAGZ;
-	if((val & 0xF) == 0)
-		Fl |= FLAGH;
-	return time;
+	r[rF] &= FLAGC;
+	++v;
+	if(v == 0)
+		r[rF] |= FLAGZ;
+	if((v & 0xf) == 0)
+		r[rF] |= FLAGH;
+	return v;
 }
 
-static int
-alu(u8int op)
+static u8int
+dec(u8int v)
 {
-	u8int val4, val8, a, b;
-	short val16;
-	int time;
-	
-	a = op & 7;
-	b = (op & 0x38) >> 3;
-	if((op >> 6) == 3){
-		val8 = fetch8();
-		time = 8;
-	}else if(a == rHL){
-		val8 = memread(lohi(R[rL], R[rH]));
-		time = 8;
-	}else{
-		val8 = R[a];
-		time = 4;
-	}
-	switch(b){
-	case 0:
-	case 1:
-		val16 = (ushort)(R[rA]) + (ushort)(val8);
-		val4 = (R[rA] & 0xF) + (val8 & 0xF);
-		if(b == 1 && (Fl & FLAGC)){
-			val16++;
-			val4++;
-		}
-		Fl = 0;
-		val8 = val16;
-		if(val16 >= 0x100)
-			Fl |= FLAGC;
-		if(val4 >= 0x10)
-			Fl |= FLAGH;
-		break;
-	case 2:
-	case 3:
-	case 7:
-		val16 = (ushort)R[rA];
-		val16 -= (ushort)val8;
-		val4 = val8 & 0xF;
-		if(b == 3 && (Fl & FLAGC)){
-			val16--;
-			val4++;
-		}
-		val8 = val16;
-		Fl = FLAGN;
-		if(val16 < 0)
-			Fl |= FLAGC;
-		if(val4 > (R[rA] & 0xF))
-			Fl |= FLAGH;
-		break;
-	case 4:
-		val8 &= R[rA];
-		Fl = FLAGH;
-		break;
-	case 5:
-		val8 ^= R[rA];
-		Fl = 0;
-		break;
-	default:
-		Fl = 0;
-		val8 |= R[rA];
-	}
-	if(val8 == 0)
-		Fl |= FLAGZ;
-	if(b != 7)
-		R[rA] = val8;
-	return time;
+	--v;
+	r[rF] = r[rF] & FLAGC | FLAGN;
+	if(v == 0)
+		r[rF] |= FLAGZ;
+	if((v & 0xf) == 0xf)
+		r[rF] |= FLAGH;
+	return v;
 }
 
 static int
-jr(u8int op)
+addhl(u16int u)
 {
-	u8int a;
-	u16int addr;
-	short step;
+	u32int v;
 	
-	a = (op & 0x38) >> 3;
-	switch(a){
-	case 0:
-		return 4;
-	case 1:
-		addr = fetch16();
-		memwrite(addr, sp);
-		memwrite(addr + 1, sp >> 8);
-		return 8;
-	}
-	step = (short)(schar)fetch8();
-	switch(a){
-	case 2:
-		return 4;
-	case 4:
-		if(Fl & FLAGZ)
-			return 8;
-		break;
-	case 5:
-		if((Fl & FLAGZ) == 0)
-			return 8;
-		break;
-	case 6:
-		if(Fl & FLAGC)
-			return 8;
-		break;
-	case 7:
-		if((Fl & FLAGC) == 0)
-			return 8;
-	}
-	pc += step;
+	r[rF] &= ~(FLAGN|FLAGC|FLAGH);
+	v = HL() + u;
+	if((v & 0x10000) != 0)
+		r[rF] |= FLAGC;
+	if((HL() & 0xfff) + (u & 0xfff) >= 0x1000)
+		r[rF] |= FLAGH;
+	r[rL] = v;
+	r[rH] = v >> 8;
 	return 8;
 }
 
-static int
-jp(u8int op)
+static void
+adchl(u16int u)
 {
-	u16int addr;
+	u32int v, v4;
 	
-	addr = fetch16();
-	if(op != 0xC3){
-		switch((op & 0x38) >> 3){
-		case 0:
-			if(Fl & FLAGZ)
-				return 12;
-			break;
-		case 1:
-			if((Fl & FLAGZ) == 0)
-				return 12;
-			break;
-		case 2:
-			if(Fl & FLAGC)
-				return 12;
-			break;
-		case 3:
-			if((Fl & FLAGC) == 0)
-				return 12;
-			break;
-		}
-	}
-	pc = addr;
-	return 12;
+	v = HL() + u + (r[rF] & FLAGC);
+	v4 = (HL() & 0xfff) + (u & 0xfff) + (r[rF] & FLAGC);
+	r[rF] = 0;
+	if((v & 0x10000) != 0)
+		r[rF] |= FLAGC;
+	if((v4 & 0x1000) != 0)
+		r[rF] |= FLAGH;
+	if((u16int)v == 0)
+		r[rF] |= FLAGZ;
+	r[rL] = v;
+	r[rH] = v >> 8;
 }
 
-static int
-call(u8int op)
+static void
+sbchl(u16int u)
 {
-	u16int addr;
+	u32int v, v4;
 	
-	addr = fetch16();
-	if(op != 0xCD){
-		switch((op & 0x38) >> 3){
-		case 0:
-			if(Fl & FLAGZ)
-				return 12;
-			break;
-		case 1:
-			if((Fl & FLAGZ) == 0)
-				return 12;
-			break;
-		case 2:
-			if(Fl & FLAGC)
-				return 12;
-			break;
-		case 3:
-			if((Fl & FLAGC) == 0)
-				return 12;
-			break;
-		}
-	}
-	push16(pc);
-	pc = addr;
-	return 12;
+	v = HL() + (u16int)~u + (~r[rF] & FLAGC);
+	v4 = (HL() & 0xfff) + (~u & 0xfff) + (~r[rF] & FLAGC);
+	r[rF] = FLAGN;
+	if((v & 0x10000) == 0)
+		r[rF] |= FLAGC;
+	if((v4 & 0x1000) == 0)
+		r[rF] |= FLAGH;
+	if((u16int)v == 0)
+		r[rF] |= FLAGZ;
+	r[rL] = v;
+	r[rH] = v >> 8;
 }
 
 static int
-rst(u8int op)
+jump(int cc)
 {
-	u16int addr;
-
-	addr = op & 0x38;
-	push16(pc);
-	pc = addr;
-	return 32;
-}
-
-static int
-ret(u8int op)
-{
-	if(op != 0xC9 && op!= 0xD9){
-		switch((op & 0x38) >> 3){
-		case 0:
-			if(Fl & FLAGZ)
-				return 8;
-			break;
-		case 1:
-			if((Fl & FLAGZ) == 0)
-				return 8;
-			break;
-		case 2:
-			if(Fl & FLAGC)
-				return 8;
-			break;
-		case 3:
-			if((Fl & FLAGC) == 0)
-				return 8;
-			break;
-		}
-	}
-	pc = pop16();
-	if(op == 0xD9)
-		IME = 1;
-	return 8;
-}
-
-static int
-push(u8int op)
-{
-	u8int a;
-
-	a = (op & 0x38) >> 4;
-	switch(a){
-	case 0:
-		push8(R[rB]);
-		push8(R[rC]);
-		break;
-	case 1:
-		push8(R[rD]);
-		push8(R[rE]);
-		break;
-	case 2:
-		push8(R[rH]);
-		push8(R[rL]);
-		break;
-	default:
-		push8(R[rA]);
-		push8(Fl);
-		break;
-	}
+	u16int v;
+	
+	v = fetch16();
+	if(!cc)
+		return 12;
+	pc = v;
 	return 16;
 }
 
 static int
-pop(u8int op)
+call(u16int a, int cc)
 {
-	u8int a;
-	
-	a = (op & 0x38) >> 4;
-	switch(a){
-	case 0:
-		R[rC] = pop8();
-		R[rB] = pop8();
-		break;
-	case 1:
-		R[rE] = pop8();
-		R[rD] = pop8();
-		break;
-	case 2:
-		R[rL] = pop8();
-		R[rH] = pop8();
-		break;
-	default:
-		Fl = pop8() & 0xF0;
-		R[rA] = pop8();
-	}
-	return 12;
+	if(!cc)
+		return 12;
+	push16(pc);
+	pc = a;
+	return cc < 0 ? 16 : 24;
 }
 
 static int
-shift(u8int op, int cb)
+bits(void)
 {
-	u16int val;
-	u8int a, b;
-	int time;
+	u8int op, v, n, m, c;
+	u16int a;
+	int t;
 	
-	a = (op & 0x38) >> 3;
-	b = op & 7;
-	if(b == rHL){
-		val = memread(lohi(R[rL], R[rH]));
-		time = 16;
+	op = fetch8();
+	n = op & 7;
+	m = op >> 3 & 7;
+	a = HL();
+	if(n == 6){
+		v = memread(a);
+		t = 16;
 	}else{
-		val = R[b];
-		time = 8;
+		v = r[n];
+		t = 8;
 	}
-	switch(a){
+	switch(op >> 6){
 	case 0:
-		Fl = 0;
-		if(val & 0x80)
-			Fl = FLAGC;
-		val = (val << 1) | (val >> 7);
+		c = r[rF] >> 4 & 1;
+		switch(m){
+		default: r[rF] = v >> 3 & 0x10; v = v << 1 | v >> 7; break;
+		case 1:  r[rF] = v << 4 & 0x10; v = v >> 1 | v << 7; break;
+		case 2:  r[rF] = v >> 3 & 0x10; v = v << 1 | c; break;
+		case 3:  r[rF] = v << 4 & 0x10; v = v >> 1 | c << 7; break;
+		case 4:  r[rF] = v >> 3 & 0x10; v = v << 1; break;
+		case 5:  r[rF] = v << 4 & 0x10; v = v & 0x80 | v >> 1; break;
+		case 6:  r[rF] = 0; v = v << 4 | v >> 4; break;
+		case 7:  r[rF] = v << 4 & 0x10; v >>= 1; break;
+		}
+		if(v == 0)
+			r[rF] |= FLAGZ;
 		break;
 	case 1:
-		Fl = 0;
-		if(val & 1)
-			Fl = FLAGC;
-		val = (val >> 1) | (val << 7);
-		break;
+		r[rF] = r[rF] & ~(FLAGN|FLAGZ) | FLAGH;
+		if((v & 1<<m) == 0)
+			r[rF] |= FLAGZ;
+		if(n == 6)
+			t = 12;
+		return t;
 	case 2:
-		val <<= 1;
-		if(Fl & FLAGC)
-			val |= 1;
-		Fl = 0;
-		if(val & 0x100)
-			Fl = FLAGC;
+		v &= ~(1<<m);
 		break;
 	case 3:
-		if(Fl & FLAGC)
-			val |= 0x100;
-		Fl = 0;
-		if(val & 1)
-			Fl = FLAGC;
-		val >>= 1;
-		break;
-	case 4:
-		Fl = 0;
-		if(val & 0x80)
-			Fl = FLAGC;
-		val <<= 1;
-		break;
-	case 5:
-		Fl = 0;
-		if(val & 1)
-			Fl = FLAGC;
-		val = (val >> 1) | (val & 0x80);
-		break;
-	case 6:
-		val = (val << 4) | (val >> 4);
-		Fl = 0;
-		break;
-	default:
-		Fl = 0;
-		if(val & 1)
-			Fl = FLAGC;
-		val >>= 1;
+		v |= (1<<m);
 	}
-	if((val & 0xFF) == 0)
-		Fl |= FLAGZ;
-	if(b == rHL)
-		memwrite(lohi(R[rL], R[rH]), val);
+	if(n == 6)
+		memwrite(a, v);
 	else
-		R[b] = val;
-	if(!cb)
-		Fl &= FLAGC;
-	return time;
+		r[n] = v;
+	return t;
 }
 
-static int
-bit(u8int op)
-{
-	u8int val, a, b;
-	int time;
-	
-	a = (op & 0x38) >> 3;
-	b = op & 7;
-	if(b == rHL){
-		val = memread(lohi(R[rL], R[rH])),
-		time = 16;
-	}else{
-		val = R[b];
-		time = 8;
-	}
-	Fl = (Fl & FLAGC) | FLAGH;
-	if((val & (1<<a)) == 0)
-		Fl |= FLAGZ;
-	return time;
-}
-
-static int
-setres(u8int op)
-{
-	u8int val, a, b;
-	int time;
-	
-	a = (op & 0x38) >> 3;
-	b = op & 7;
-	if(b == rHL){
-		val = memread(lohi(R[rL], R[rH]));
-		time = 16;
-	}else{
-		val = R[b];
-		time = 8;
-	}
-	if(op & 0x40)
-		val |= (1 << a);
-	else
-		val &= ~(1 << a);
-	if(b == rHL)
-		memwrite(lohi(R[rL], R[rH]), val);
-	else
-		R[b] = val;
-	return time;
-}
-
-static int
-cb(void)
-{
-	u8int op;
-	
-	op = fetch8();
-	if((op & 0xC0) == 0)
-		return shift(op, 1);
-	if((op & 0xC0) == 0x40)
-		return bit(op);
-	return setres(op);
-}
-
 void
-interrupt(u8int t)
+reset(void)
 {
-	mem[IF] |= (1 << t);
+	r[rA] = 0x01;
+	r[rF] = 0xb0;
+	r[rC] = 0x13;
+	r[rE] = 0xd8;
+	r[rL] = 0x4d;
+	r[rH] = 0x01;
+	if((mode & COL) == COL)
+		r[rA] = 0x11;
+	sp = 0xfffe;
+	pc = 0x100;
 }
 
 int
 step(void)
 {
-	u8int op;
-	ushort val;
-	extern u8int daa[];
-	int val32, i;
+	u8int op, v4;
+	u16int v, w;
+	s8int s;
 
-	if(halt){
-		if(mem[IF] & mem[IE])
+	if(halt)
+		if((reg[IF] & reg[IE]) != 0)
 			halt = 0;
 		else
 			return 4;
+	if((reg[IF] & reg[IE]) != 0 && ime != 0){
+		push16(pc);
+		ime = 0;
+		v4 = reg[IF] & reg[IE];
+		v4 &= -v4;
+		reg[IF] &= ~v4;
+		for(pc = 0x40; v4 != 1; pc += 8)
+			v4 >>= 1;
+		return 12;
 	}
-	if(IME && (mem[IF] & mem[IE]))
-		for(i = 0; i < 5; i++)
-			if(mem[IF] & mem[IE] & (1<<i)){
-				mem[IF] &= ~(1<<i);
-				push16(pc);
-				IME = 0;
-				halt = 0;
-				pc = 0x40 + 8 * i;
-				break;
-			}
 	curpc = pc;
 	op = fetch8();
-	if(0){
-		print("%.4x A %.2x B %.2x C %.2x D %.2x E %.2x HL %.2x%.2x SP %.4x F %.2x ", curpc, R[rA], R[rB], R[rC], R[rD], R[rE], R[rH], R[rL], sp, Fl);
-		disasm(curpc);
+	if(trace)
+		print("%.4x %.2x AF %.2x%.2x BC %.2x%.2x DE %.2x%.2x HL %.2x%.2x SP %.4x\n", curpc, op, r[rA], r[rF], r[rB], r[rC], r[rD], r[rE], r[rH], r[rL], sp);
+	switch(op >> 6){
+	case 1: return move(op >> 3 & 7, op & 7);
+	case 2: return alu(op >> 3 & 7, op & 7);
 	}
-	if((op & 0xC7) == 0x00)
-		return jr(op);
-	if((op & 0xCF) == 0x01)
-		return ld16(op);
-	if((op & 0xCF) == 0x09)
-		return add16(op);
-	if((op & 0xC7) == 0x02)
-		return ldin(op);
-	if((op & 0xC7) == 0x03)
-		return inc16(op);
-	if((op & 0xC7) == 0x04)
-		return inc8(op);
-	if((op & 0xC7) == 0x05)
-		return dec8(op);
-	if((op & 0xC7) == 0x06)
-		return ldi(op);
-	if((op & 0xE7) == 0x07)
-		return shift(op, 0);
-	if((op & 0xC0) == 0x40)
-		return ld01(op);
-	if((op & 0xC0) == 0x80 || (op & 0xC7) == 0xC6)
-		return alu(op);
-	if((op & 0xE7) == 0xC0 || op == 0xC9 || op == 0xD9)
-		return ret(op);
-	if((op & 0xCF) == 0xC1)
-		return pop(op);
-	if((op & 0xE7) == 0xC2 || op == 0xC3)
-		return jp(op);
-	if((op & 0xE7) == 0xC4 || op == 0xCD)
-		return call(op);
-	if((op & 0xCF) == 0xC5)
-		return push(op);
-	if((op & 0xC7) == 0xC7)
-		return rst(op);
 	switch(op){
-	case 0x27:
-		i = (((int)R[rA]) + (((int)Fl) * 16)) * 2;
-		R[rA] = daa[i];
-		Fl = daa[i+1];
+	case 0x00: return 4;
+	case 0x10:
+		if((mode & CGB) != 0 && (reg[KEY1] & 1) != 0){
+			reg[DIV] += divclock - clock >> 7 - ((mode & TURBO) != 0);
+			divclock = clock;
+			mode ^= TURBO;
+			timertac(reg[TAC], 1);
+			reg[KEY1] ^= 0x81;
+			return 4;
+		}
+		print("STOP ignored (pc=%.4ux)\n", curpc);
 		return 4;
-	case 0x2F:
-		R[rA] = ~R[rA];
-		Fl |= FLAGN | FLAGH;
+	case 0x20: return branch((r[rF] & FLAGZ) == 0, 0);
+	case 0x30: return branch((r[rF] & FLAGC) == 0, 0);
+	case 0x01: r[rC] = fetch8(); r[rB] = fetch8(); return 12;
+	case 0x11: r[rE] = fetch8(); r[rD] = fetch8(); return 12;
+	case 0x21: r[rL] = fetch8(); r[rH] = fetch8(); return 12;
+	case 0x31: sp = fetch16(); return 12;
+	case 0x02: memwrite(BC(), r[rA]); return 8;
+	case 0x12: memwrite(DE(), r[rA]); return 8;
+	case 0x22: memwrite(HL(), r[rA]); if(++r[rL] == 0) r[rH]++; return 8;
+	case 0x32: memwrite(HL(), r[rA]); if(r[rL]-- == 0) r[rH]--; return 8;
+	case 0x03: if(++r[rC] == 0) r[rB]++; return 8;
+	case 0x13: if(++r[rE] == 0) r[rD]++; return 8;
+	case 0x23: if(++r[rL] == 0) r[rH]++; return 8;
+	case 0x33: sp++; return 8;
+	case 0x04: inc(r[rB]++); return 4;
+	case 0x14: inc(r[rD]++); return 4;
+	case 0x24: inc(r[rH]++); return 4;
+	case 0x34: memwrite(HL(), inc(memread(HL()))); return 12;
+	case 0x05: dec(r[rB]--); return 4;
+	case 0x15: dec(r[rD]--); return 4;
+	case 0x25: dec(r[rH]--); return 4;
+	case 0x35: memwrite(HL(), dec(memread(HL()))); return 12;
+	case 0x06: r[rB] = fetch8(); return 8;
+	case 0x16: r[rD] = fetch8(); return 8;
+	case 0x26: r[rH] = fetch8(); return 8;
+	case 0x36: memwrite(HL(), fetch8()); return 12;
+	case 0x07:
+		r[rF] = r[rA] >> 3 & 0x10;
+		r[rA] = r[rA] << 1 | r[rA] >> 7;
 		return 4;
-	case 0x37:
-		Fl = (Fl & FLAGZ) | FLAGC;
+	case 0x17:
+		v = r[rF] >> 4 & 1;
+		r[rF] = r[rA] >> 3 & 0x10;
+		r[rA] = r[rA] << 1 | v;	
 		return 4;
-	case 0x3F:
-		Fl &= FLAGZ | FLAGC;
-		Fl ^= FLAGC;
+	case 0x27:
+		if(r[rA] > 0x99 && (r[rF] & FLAGN) == 0 || (r[rF] & FLAGC) != 0){
+			r[rF] |= FLAGC;
+			v = 0x60;
+		}else{
+			r[rF] &= ~FLAGC;
+			v = 0;
+		}
+		if((r[rA] & 0xf) > 9 && (r[rF] & FLAGN) == 0 || (r[rF] & FLAGH) != 0)
+			v |= 6;
+		if((r[rF] & FLAGN) != 0)
+			r[rA] -= v;
+		else
+			r[rA] += v;
+		r[rF] &= ~(FLAGZ|FLAGH);
+		if(r[rA] == 0)
+			r[rF] |= FLAGZ;
 		return 4;
-	case 0xE0:
-		memwrite(lohi(fetch8(), 0xFF), R[rA]);
-		return 8;
-	case 0xE2:
-		memwrite(lohi(R[rC], 0xFF), R[rA]);
-		return 8;
-	case 0xE8:
-		val = (short)(schar)fetch8();
-		val32 = (uint)sp + (uint)val;
-		Fl = 0;
-		if(((sp & 0xFF) + (val & 0xFF)) > 0xFF)
-			Fl |= FLAGC;
-		if(((sp & 0xF) + (val & 0xF)) > 0xF)
-			Fl |= FLAGH;
-		sp = val32;
-		return 16;
-	case 0xE9:
-		pc = lohi(R[rL], R[rH]);
+	case 0x37: r[rF] = r[rF] & ~(FLAGN | FLAGH) | FLAGC; return 4;
+	case 0x08: write16(fetch16(), sp); return 20;
+	case 0x18: return branch(1, 0);
+	case 0x28: return branch((r[rF] & FLAGZ) != 0, 0);
+	case 0x38: return branch((r[rF] & FLAGC) != 0, 0);
+	case 0x09: return addhl(BC());
+	case 0x19: return addhl(DE());
+	case 0x29: return addhl(HL());
+	case 0x39: return addhl(sp);
+	case 0x0a: r[rA] = memread(BC()); return 8;
+	case 0x1a: r[rA] = memread(DE()); return 8;
+	case 0x2a: r[rA] = memread(HL()); if(++r[rL] == 0) r[rH]++; return 8;
+	case 0x3a: r[rA] = memread(HL()); if(r[rL]-- == 0) r[rH]--; return 8;
+	case 0x0b: if(r[rC]-- == 0) r[rB]--; return 8;
+	case 0x1b: if(r[rE]-- == 0) r[rD]--; return 8;
+	case 0x2b: if(r[rL]-- == 0) r[rH]--; return 8;
+	case 0x3b: sp--; return 8;
+	case 0x0c: inc(r[rC]++); return 4;
+	case 0x1c: inc(r[rE]++); return 4;
+	case 0x2c: inc(r[rL]++); return 4;
+	case 0x3c: inc(r[rA]++); return 4;
+	case 0x0d: dec(r[rC]--); return 4;
+	case 0x1d: dec(r[rE]--); return 4;
+	case 0x2d: dec(r[rL]--); return 4;
+	case 0x3d: dec(r[rA]--); return 4;
+	case 0x0e: r[rC] = fetch8(); return 8;
+	case 0x1e: r[rE] = fetch8(); return 8;
+	case 0x2e: r[rL] = fetch8(); return 8;
+	case 0x3e: r[rA] = fetch8(); return 8;
+	case 0x0f:
+		r[rF] = r[rA] << 4 & 0x10;
+		r[rA] = r[rA] >> 1 | r[rA] << 7;
 		return 4;
-	case 0xEA:
-		memwrite(fetch16(), R[rA]);
-		return 16;
-	case 0xF0:
-		R[rA] = memread(lohi(fetch8(), 0xFF));
-		return 12;
-	case 0xFA:
-		R[rA] = memread(fetch16());
-		return 16;
-	case 0xF2:
-		R[rA] = memread(lohi(R[rC], 0xFF));
-		return 8;
-	case 0xCB:
-		return cb();
-	case 0xF3:
-		IME= 0;
+	case 0x1f:
+		v = r[rF] << 3 & 0x80;
+		r[rF] = r[rA] << 4 & 0x10;
+		r[rA] = r[rA] >> 1 | v;
 		return 4;
-	case 0xF8:
-		val = (short)(schar)fetch8();
-		val32 = (uint)sp + (uint)val;
-		Fl = 0;
-		if(((sp & 0xFF) + (val & 0xFF)) > 0xFF)
-			Fl |= FLAGC;
-		if(((sp & 0xF) + (val & 0xF)) > 0xF)
-			Fl |= FLAGH;
-		R[rL] = val32;
-		R[rH] = val32 >> 8;
-		return 12;
-	case 0xF9:
-		sp = lohi(R[rL], R[rH]);
-		return 8;
-	case 0xFB:
-		IME = 1;
+	case 0x2f:
+		r[rF] |= FLAGN|FLAGH;
+		r[rA] ^= 0xff;
 		return 4;
-	default:
-		invalid();
+	case 0x3f:
+		r[rF] = r[rF] & ~(FLAGN|FLAGH) ^ FLAGC;
+		return 4;
+	case 0xc0: if((r[rF] & FLAGZ) == 0) {pc = pop16(); return 20;} return 8;
+	case 0xd0: if((r[rF] & FLAGC) == 0) {pc = pop16(); return 20;} return 8;
+	case 0xe0: memwrite(0xff00 | fetch8(), r[rA]); return 12;
+	case 0xf0: r[rA] = memread(0xff00 | fetch8()); return 12;
+	case 0xc1: r[rC] = pop8(); r[rB] = pop8(); return 12;
+	case 0xd1: r[rE] = pop8(); r[rD] = pop8(); return 12;
+	case 0xe1: r[rL] = pop8(); r[rH] = pop8(); return 12;
+	case 0xf1: r[rF] = pop8() & 0xf0; r[rA] = pop8(); return 12;
+	case 0xc2: return jump((r[rF] & FLAGZ) == 0);
+	case 0xd2: return jump((r[rF] & FLAGC) == 0);
+	case 0xe2: memwrite(0xff00 | r[rC], r[rA]); return 8;
+	case 0xf2: r[rA] = memread(0xff00 | r[rC]); return 8;
+	case 0xc3: return jump(1);
+	case 0xf3: ime = 0; return 4;
+	case 0xc4: return call(fetch16(), (r[rF] & FLAGZ) == 0);
+	case 0xd4: return call(fetch16(), (r[rF] & FLAGC) == 0);
+	case 0xc5: push8(r[rB]); push8(r[rC]); return 16;
+	case 0xd5: push8(r[rD]); push8(r[rE]); return 16;
+	case 0xe5: push8(r[rH]); push8(r[rL]); return 16;
+	case 0xf5: push8(r[rA]); push8(r[rF]); return 16;
+	case 0xc6: return alu(0, 8);
+	case 0xd6: return alu(2, 8);
+	case 0xe6: return alu(4, 8);
+	case 0xf6: return alu(6, 8);
+	case 0xc7: return call(0x00, -1);
+	case 0xd7: return call(0x10, -1);
+	case 0xe7: return call(0x20, -1);
+	case 0xf7: return call(0x30, -1);
+	case 0xc8: if((r[rF] & FLAGZ) != 0) {pc = pop16(); return 20;} return 8;
+	case 0xd8: if((r[rF] & FLAGC) != 0) {pc = pop16(); return 20;} return 8;
+	case 0xe8: case 0xf8:
+		s = fetch8();
+		v = sp + s;
+		v4 = (sp & 0xf) + (s & 0xf);
+		w = (sp & 0xff) + (s & 0xff);
+		r[rF] = 0;
+		if(v4 >= 0x10)
+			r[rF] |= FLAGH;
+		if(w >= 0x100)
+			r[rF] |= FLAGC;	
+		if(op == 0xe8){
+			sp = v;
+			return 16;
+		}else{
+			r[rL] = v;
+			r[rH] = v >> 8;
+			return 12;
+		}
+	case 0xc9: pc = pop16(); return 16;
+	case 0xd9: pc = pop16(); ime = 1; return 16;
+	case 0xe9: pc = HL(); return 4;
+	case 0xf9: sp = HL(); return 8;
+	case 0xca: return jump((r[rF] & FLAGZ) != 0);
+	case 0xda: return jump((r[rF] & FLAGC) != 0);
+	case 0xea: memwrite(fetch16(), r[rA]); return 16;
+	case 0xfa: r[rA] = memread(fetch16()); return 16;
+	case 0xcb: return bits();
+	case 0xfb: ime = 1; return 4;
+	case 0xcc: return call(fetch16(), (r[rF] & FLAGZ) != 0);
+	case 0xdc: return call(fetch16(), (r[rF] & FLAGC) != 0);
+	case 0xcd: return call(fetch16(), 1);
+	case 0xce: return alu(1, 8);
+	case 0xde: return alu(3, 8);
+	case 0xee: return alu(5, 8);
+	case 0xfe: return alu(7, 8);
+	case 0xcf: return call(0x08, -1);
+	case 0xdf: return call(0x18, -1);
+	case 0xef: return call(0x28, -1);
+	case 0xff: return call(0x38, -1);
 	}
+	sysfatal("undefined opcode %#.2x at pc=%#.4x", op, curpc);
 	return 0;
 }
--- a/sys/src/games/gb/daa.c
+++ /dev/null
@@ -1,465 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include "dat.h"
-#include "fns.h"
-
-u8int daa[] = {
-	0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 
-	0x09, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x10, 0x00, 0x11, 0x00, 
-	0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x20, 0x00, 
-	0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 
-	0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 
-	0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 
-	0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 
-	0x45, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 
-	0x48, 0x00, 0x49, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x50, 0x00, 
-	0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 
-	0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 
-	0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x71, 0x00, 
-	0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 
-	0x75, 0x00, 0x76, 0x00, 0x77, 0x00, 0x78, 0x00, 0x79, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 
-	0x84, 0x00, 0x85, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 
-	0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 
-	0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 
-	0x99, 0x00, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x00, 0x90, 0x01, 0x10, 
-	0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x10, 0x10, 
-	0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 
-	0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 
-	0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 
-	0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 
-	0x35, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 
-	0x38, 0x10, 0x39, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x40, 0x10, 
-	0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 
-	0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 
-	0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x60, 0x10, 0x61, 0x10, 
-	0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 
-	0x65, 0x10, 0x66, 0x10, 0x67, 0x10, 0x68, 0x10, 0x69, 0x10, 0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 
-	0x74, 0x10, 0x75, 0x10, 0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 0x75, 0x10, 0x76, 0x10, 
-	0x77, 0x10, 0x78, 0x10, 0x79, 0x10, 0x80, 0x10, 0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 
-	0x80, 0x10, 0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 0x86, 0x10, 0x87, 0x10, 0x88, 0x10, 
-	0x89, 0x10, 0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 0x90, 0x10, 0x91, 0x10, 
-	0x92, 0x10, 0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 0x96, 0x10, 0x97, 0x10, 0x98, 0x10, 0x99, 0x10, 0xA0, 0x10, 
-	0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA0, 0x10, 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 
-	0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, 0xA9, 0x10, 0xB0, 0x10, 0xB1, 0x10, 0xB2, 0x10, 
-	0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB0, 0x10, 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 
-	0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, 0xB9, 0x10, 0xC0, 0x10, 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 
-	0xC5, 0x10, 0xC0, 0x10, 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xC6, 0x10, 0xC7, 0x10, 
-	0xC8, 0x10, 0xC9, 0x10, 0xD0, 0x10, 0xD1, 0x10, 0xD2, 0x10, 0xD3, 0x10, 0xD4, 0x10, 0xD5, 0x10, 0xD0, 0x10, 
-	0xD1, 0x10, 0xD2, 0x10, 0xD3, 0x10, 0xD4, 0x10, 0xD5, 0x10, 0xD6, 0x10, 0xD7, 0x10, 0xD8, 0x10, 0xD9, 0x10, 
-	0xE0, 0x10, 0xE1, 0x10, 0xE2, 0x10, 0xE3, 0x10, 0xE4, 0x10, 0xE5, 0x10, 0xE0, 0x10, 0xE1, 0x10, 0xE2, 0x10, 
-	0xE3, 0x10, 0xE4, 0x10, 0xE5, 0x10, 0xE6, 0x10, 0xE7, 0x10, 0xE8, 0x10, 0xE9, 0x10, 0xF0, 0x10, 0xF1, 0x10, 
-	0xF2, 0x10, 0xF3, 0x10, 0xF4, 0x10, 0xF5, 0x10, 0xF0, 0x10, 0xF1, 0x10, 0xF2, 0x10, 0xF3, 0x10, 0xF4, 0x10, 
-	0xF5, 0x10, 0xF6, 0x10, 0xF7, 0x10, 0xF8, 0x10, 0xF9, 0x10, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 
-	0x04, 0x10, 0x05, 0x10, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 
-	0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 
-	0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 
-	0x19, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x20, 0x10, 0x21, 0x10, 
-	0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x30, 0x10, 
-	0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 
-	0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 
-	0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 
-	0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 
-	0x55, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 
-	0x58, 0x10, 0x59, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x06, 0x00, 
-	0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 
-	0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 
-	0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x20, 0x00, 0x21, 0x00, 
-	0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 
-	0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 
-	0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 
-	0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 
-	0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 
-	0x4F, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 
-	0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, 0x60, 0x00, 
-	0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 
-	0x6A, 0x00, 0x6B, 0x00, 0x6C, 0x00, 0x6D, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 
-	0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 0x77, 0x00, 0x78, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B, 0x00, 
-	0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 
-	0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 
-	0x8E, 0x00, 0x8F, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 
-	0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, 
-	0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 
-	0x09, 0x10, 0x0A, 0x10, 0x0B, 0x10, 0x0C, 0x10, 0x0D, 0x10, 0x0E, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x10, 
-	0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x1A, 0x10, 
-	0x1B, 0x10, 0x1C, 0x10, 0x1D, 0x10, 0x1E, 0x10, 0x1F, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 
-	0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x2A, 0x10, 0x2B, 0x10, 0x2C, 0x10, 
-	0x2D, 0x10, 0x2E, 0x10, 0x2F, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 
-	0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x3A, 0x10, 0x3B, 0x10, 0x3C, 0x10, 0x3D, 0x10, 0x3E, 0x10, 
-	0x3F, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 
-	0x48, 0x10, 0x49, 0x10, 0x4A, 0x10, 0x4B, 0x10, 0x4C, 0x10, 0x4D, 0x10, 0x4E, 0x10, 0x4F, 0x10, 0x50, 0x10, 
-	0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 
-	0x5A, 0x10, 0x5B, 0x10, 0x5C, 0x10, 0x5D, 0x10, 0x5E, 0x10, 0x5F, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 
-	0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x66, 0x10, 0x67, 0x10, 0x68, 0x10, 0x69, 0x10, 0x6A, 0x10, 0x6B, 0x10, 
-	0x6C, 0x10, 0x6D, 0x10, 0x6E, 0x10, 0x6F, 0x10, 0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 
-	0x75, 0x10, 0x76, 0x10, 0x77, 0x10, 0x78, 0x10, 0x79, 0x10, 0x7A, 0x10, 0x7B, 0x10, 0x7C, 0x10, 0x7D, 0x10, 
-	0x7E, 0x10, 0x7F, 0x10, 0x80, 0x10, 0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 0x86, 0x10, 
-	0x87, 0x10, 0x88, 0x10, 0x89, 0x10, 0x8A, 0x10, 0x8B, 0x10, 0x8C, 0x10, 0x8D, 0x10, 0x8E, 0x10, 0x8F, 0x10, 
-	0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 0x96, 0x10, 0x97, 0x10, 0x98, 0x10, 
-	0x99, 0x10, 0x9A, 0x10, 0x9B, 0x10, 0x9C, 0x10, 0x9D, 0x10, 0x9E, 0x10, 0x9F, 0x10, 0xA0, 0x10, 0xA1, 0x10, 
-	0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, 0xA9, 0x10, 0xAA, 0x10, 
-	0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 
-	0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 
-	0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 
-	0xC6, 0x10, 0xC7, 0x10, 0xC8, 0x10, 0xC9, 0x10, 0xCA, 0x10, 0xCB, 0x10, 0xCC, 0x10, 0xCD, 0x10, 0xCE, 0x10, 
-	0xCF, 0x10, 0xD0, 0x10, 0xD1, 0x10, 0xD2, 0x10, 0xD3, 0x10, 0xD4, 0x10, 0xD5, 0x10, 0xD6, 0x10, 0xD7, 0x10, 
-	0xD8, 0x10, 0xD9, 0x10, 0xDA, 0x10, 0xDB, 0x10, 0xDC, 0x10, 0xDD, 0x10, 0xDE, 0x10, 0xDF, 0x10, 0xE0, 0x10, 
-	0xE1, 0x10, 0xE2, 0x10, 0xE3, 0x10, 0xE4, 0x10, 0xE5, 0x10, 0xE6, 0x10, 0xE7, 0x10, 0xE8, 0x10, 0xE9, 0x10, 
-	0xEA, 0x10, 0xEB, 0x10, 0xEC, 0x10, 0xED, 0x10, 0xEE, 0x10, 0xEF, 0x10, 0xF0, 0x10, 0xF1, 0x10, 0xF2, 0x10, 
-	0xF3, 0x10, 0xF4, 0x10, 0xF5, 0x10, 0xF6, 0x10, 0xF7, 0x10, 0xF8, 0x10, 0xF9, 0x10, 0xFA, 0x10, 0xFB, 0x10, 
-	0xFC, 0x10, 0xFD, 0x10, 0xFE, 0x10, 0xFF, 0x10, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 
-	0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x0A, 0x10, 0x0B, 0x10, 0x0C, 0x10, 0x0D, 0x10, 
-	0x0E, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 
-	0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x1A, 0x10, 0x1B, 0x10, 0x1C, 0x10, 0x1D, 0x10, 0x1E, 0x10, 0x1F, 0x10, 
-	0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 
-	0x29, 0x10, 0x2A, 0x10, 0x2B, 0x10, 0x2C, 0x10, 0x2D, 0x10, 0x2E, 0x10, 0x2F, 0x10, 0x30, 0x10, 0x31, 0x10, 
-	0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x3A, 0x10, 
-	0x3B, 0x10, 0x3C, 0x10, 0x3D, 0x10, 0x3E, 0x10, 0x3F, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 
-	0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 0x4A, 0x10, 0x4B, 0x10, 0x4C, 0x10, 
-	0x4D, 0x10, 0x4E, 0x10, 0x4F, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 
-	0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x5A, 0x10, 0x5B, 0x10, 0x5C, 0x10, 0x5D, 0x10, 0x5E, 0x10, 
-	0x5F, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x00, 0xC0, 0x01, 0x40, 
-	0x02, 0x40, 0x03, 0x40, 0x04, 0x40, 0x05, 0x40, 0x06, 0x40, 0x07, 0x40, 0x08, 0x40, 0x09, 0x40, 0x0A, 0x40, 
-	0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x40, 0x0E, 0x40, 0x0F, 0x40, 0x10, 0x40, 0x11, 0x40, 0x12, 0x40, 0x13, 0x40, 
-	0x14, 0x40, 0x15, 0x40, 0x16, 0x40, 0x17, 0x40, 0x18, 0x40, 0x19, 0x40, 0x1A, 0x40, 0x1B, 0x40, 0x1C, 0x40, 
-	0x1D, 0x40, 0x1E, 0x40, 0x1F, 0x40, 0x20, 0x40, 0x21, 0x40, 0x22, 0x40, 0x23, 0x40, 0x24, 0x40, 0x25, 0x40, 
-	0x26, 0x40, 0x27, 0x40, 0x28, 0x40, 0x29, 0x40, 0x2A, 0x40, 0x2B, 0x40, 0x2C, 0x40, 0x2D, 0x40, 0x2E, 0x40, 
-	0x2F, 0x40, 0x30, 0x40, 0x31, 0x40, 0x32, 0x40, 0x33, 0x40, 0x34, 0x40, 0x35, 0x40, 0x36, 0x40, 0x37, 0x40, 
-	0x38, 0x40, 0x39, 0x40, 0x3A, 0x40, 0x3B, 0x40, 0x3C, 0x40, 0x3D, 0x40, 0x3E, 0x40, 0x3F, 0x40, 0x40, 0x40, 
-	0x41, 0x40, 0x42, 0x40, 0x43, 0x40, 0x44, 0x40, 0x45, 0x40, 0x46, 0x40, 0x47, 0x40, 0x48, 0x40, 0x49, 0x40, 
-	0x4A, 0x40, 0x4B, 0x40, 0x4C, 0x40, 0x4D, 0x40, 0x4E, 0x40, 0x4F, 0x40, 0x50, 0x40, 0x51, 0x40, 0x52, 0x40, 
-	0x53, 0x40, 0x54, 0x40, 0x55, 0x40, 0x56, 0x40, 0x57, 0x40, 0x58, 0x40, 0x59, 0x40, 0x5A, 0x40, 0x5B, 0x40, 
-	0x5C, 0x40, 0x5D, 0x40, 0x5E, 0x40, 0x5F, 0x40, 0x60, 0x40, 0x61, 0x40, 0x62, 0x40, 0x63, 0x40, 0x64, 0x40, 
-	0x65, 0x40, 0x66, 0x40, 0x67, 0x40, 0x68, 0x40, 0x69, 0x40, 0x6A, 0x40, 0x6B, 0x40, 0x6C, 0x40, 0x6D, 0x40, 
-	0x6E, 0x40, 0x6F, 0x40, 0x70, 0x40, 0x71, 0x40, 0x72, 0x40, 0x73, 0x40, 0x74, 0x40, 0x75, 0x40, 0x76, 0x40, 
-	0x77, 0x40, 0x78, 0x40, 0x79, 0x40, 0x7A, 0x40, 0x7B, 0x40, 0x7C, 0x40, 0x7D, 0x40, 0x7E, 0x40, 0x7F, 0x40, 
-	0x80, 0x40, 0x81, 0x40, 0x82, 0x40, 0x83, 0x40, 0x84, 0x40, 0x85, 0x40, 0x86, 0x40, 0x87, 0x40, 0x88, 0x40, 
-	0x89, 0x40, 0x8A, 0x40, 0x8B, 0x40, 0x8C, 0x40, 0x8D, 0x40, 0x8E, 0x40, 0x8F, 0x40, 0x90, 0x40, 0x91, 0x40, 
-	0x92, 0x40, 0x93, 0x40, 0x94, 0x40, 0x95, 0x40, 0x96, 0x40, 0x97, 0x40, 0x98, 0x40, 0x99, 0x40, 0x9A, 0x40, 
-	0x9B, 0x40, 0x9C, 0x40, 0x9D, 0x40, 0x9E, 0x40, 0x9F, 0x40, 0xA0, 0x40, 0xA1, 0x40, 0xA2, 0x40, 0xA3, 0x40, 
-	0xA4, 0x40, 0xA5, 0x40, 0xA6, 0x40, 0xA7, 0x40, 0xA8, 0x40, 0xA9, 0x40, 0xAA, 0x40, 0xAB, 0x40, 0xAC, 0x40, 
-	0xAD, 0x40, 0xAE, 0x40, 0xAF, 0x40, 0xB0, 0x40, 0xB1, 0x40, 0xB2, 0x40, 0xB3, 0x40, 0xB4, 0x40, 0xB5, 0x40, 
-	0xB6, 0x40, 0xB7, 0x40, 0xB8, 0x40, 0xB9, 0x40, 0xBA, 0x40, 0xBB, 0x40, 0xBC, 0x40, 0xBD, 0x40, 0xBE, 0x40, 
-	0xBF, 0x40, 0xC0, 0x40, 0xC1, 0x40, 0xC2, 0x40, 0xC3, 0x40, 0xC4, 0x40, 0xC5, 0x40, 0xC6, 0x40, 0xC7, 0x40, 
-	0xC8, 0x40, 0xC9, 0x40, 0xCA, 0x40, 0xCB, 0x40, 0xCC, 0x40, 0xCD, 0x40, 0xCE, 0x40, 0xCF, 0x40, 0xD0, 0x40, 
-	0xD1, 0x40, 0xD2, 0x40, 0xD3, 0x40, 0xD4, 0x40, 0xD5, 0x40, 0xD6, 0x40, 0xD7, 0x40, 0xD8, 0x40, 0xD9, 0x40, 
-	0xDA, 0x40, 0xDB, 0x40, 0xDC, 0x40, 0xDD, 0x40, 0xDE, 0x40, 0xDF, 0x40, 0xE0, 0x40, 0xE1, 0x40, 0xE2, 0x40, 
-	0xE3, 0x40, 0xE4, 0x40, 0xE5, 0x40, 0xE6, 0x40, 0xE7, 0x40, 0xE8, 0x40, 0xE9, 0x40, 0xEA, 0x40, 0xEB, 0x40, 
-	0xEC, 0x40, 0xED, 0x40, 0xEE, 0x40, 0xEF, 0x40, 0xF0, 0x40, 0xF1, 0x40, 0xF2, 0x40, 0xF3, 0x40, 0xF4, 0x40, 
-	0xF5, 0x40, 0xF6, 0x40, 0xF7, 0x40, 0xF8, 0x40, 0xF9, 0x40, 0xFA, 0x40, 0xFB, 0x40, 0xFC, 0x40, 0xFD, 0x40, 
-	0xFE, 0x40, 0xFF, 0x40, 0xA0, 0x50, 0xA1, 0x50, 0xA2, 0x50, 0xA3, 0x50, 0xA4, 0x50, 0xA5, 0x50, 0xA6, 0x50, 
-	0xA7, 0x50, 0xA8, 0x50, 0xA9, 0x50, 0xAA, 0x50, 0xAB, 0x50, 0xAC, 0x50, 0xAD, 0x50, 0xAE, 0x50, 0xAF, 0x50, 
-	0xB0, 0x50, 0xB1, 0x50, 0xB2, 0x50, 0xB3, 0x50, 0xB4, 0x50, 0xB5, 0x50, 0xB6, 0x50, 0xB7, 0x50, 0xB8, 0x50, 
-	0xB9, 0x50, 0xBA, 0x50, 0xBB, 0x50, 0xBC, 0x50, 0xBD, 0x50, 0xBE, 0x50, 0xBF, 0x50, 0xC0, 0x50, 0xC1, 0x50, 
-	0xC2, 0x50, 0xC3, 0x50, 0xC4, 0x50, 0xC5, 0x50, 0xC6, 0x50, 0xC7, 0x50, 0xC8, 0x50, 0xC9, 0x50, 0xCA, 0x50, 
-	0xCB, 0x50, 0xCC, 0x50, 0xCD, 0x50, 0xCE, 0x50, 0xCF, 0x50, 0xD0, 0x50, 0xD1, 0x50, 0xD2, 0x50, 0xD3, 0x50, 
-	0xD4, 0x50, 0xD5, 0x50, 0xD6, 0x50, 0xD7, 0x50, 0xD8, 0x50, 0xD9, 0x50, 0xDA, 0x50, 0xDB, 0x50, 0xDC, 0x50, 
-	0xDD, 0x50, 0xDE, 0x50, 0xDF, 0x50, 0xE0, 0x50, 0xE1, 0x50, 0xE2, 0x50, 0xE3, 0x50, 0xE4, 0x50, 0xE5, 0x50, 
-	0xE6, 0x50, 0xE7, 0x50, 0xE8, 0x50, 0xE9, 0x50, 0xEA, 0x50, 0xEB, 0x50, 0xEC, 0x50, 0xED, 0x50, 0xEE, 0x50, 
-	0xEF, 0x50, 0xF0, 0x50, 0xF1, 0x50, 0xF2, 0x50, 0xF3, 0x50, 0xF4, 0x50, 0xF5, 0x50, 0xF6, 0x50, 0xF7, 0x50, 
-	0xF8, 0x50, 0xF9, 0x50, 0xFA, 0x50, 0xFB, 0x50, 0xFC, 0x50, 0xFD, 0x50, 0xFE, 0x50, 0xFF, 0x50, 0x00, 0xD0, 
-	0x01, 0x50, 0x02, 0x50, 0x03, 0x50, 0x04, 0x50, 0x05, 0x50, 0x06, 0x50, 0x07, 0x50, 0x08, 0x50, 0x09, 0x50, 
-	0x0A, 0x50, 0x0B, 0x50, 0x0C, 0x50, 0x0D, 0x50, 0x0E, 0x50, 0x0F, 0x50, 0x10, 0x50, 0x11, 0x50, 0x12, 0x50, 
-	0x13, 0x50, 0x14, 0x50, 0x15, 0x50, 0x16, 0x50, 0x17, 0x50, 0x18, 0x50, 0x19, 0x50, 0x1A, 0x50, 0x1B, 0x50, 
-	0x1C, 0x50, 0x1D, 0x50, 0x1E, 0x50, 0x1F, 0x50, 0x20, 0x50, 0x21, 0x50, 0x22, 0x50, 0x23, 0x50, 0x24, 0x50, 
-	0x25, 0x50, 0x26, 0x50, 0x27, 0x50, 0x28, 0x50, 0x29, 0x50, 0x2A, 0x50, 0x2B, 0x50, 0x2C, 0x50, 0x2D, 0x50, 
-	0x2E, 0x50, 0x2F, 0x50, 0x30, 0x50, 0x31, 0x50, 0x32, 0x50, 0x33, 0x50, 0x34, 0x50, 0x35, 0x50, 0x36, 0x50, 
-	0x37, 0x50, 0x38, 0x50, 0x39, 0x50, 0x3A, 0x50, 0x3B, 0x50, 0x3C, 0x50, 0x3D, 0x50, 0x3E, 0x50, 0x3F, 0x50, 
-	0x40, 0x50, 0x41, 0x50, 0x42, 0x50, 0x43, 0x50, 0x44, 0x50, 0x45, 0x50, 0x46, 0x50, 0x47, 0x50, 0x48, 0x50, 
-	0x49, 0x50, 0x4A, 0x50, 0x4B, 0x50, 0x4C, 0x50, 0x4D, 0x50, 0x4E, 0x50, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x50, 
-	0x52, 0x50, 0x53, 0x50, 0x54, 0x50, 0x55, 0x50, 0x56, 0x50, 0x57, 0x50, 0x58, 0x50, 0x59, 0x50, 0x5A, 0x50, 
-	0x5B, 0x50, 0x5C, 0x50, 0x5D, 0x50, 0x5E, 0x50, 0x5F, 0x50, 0x60, 0x50, 0x61, 0x50, 0x62, 0x50, 0x63, 0x50, 
-	0x64, 0x50, 0x65, 0x50, 0x66, 0x50, 0x67, 0x50, 0x68, 0x50, 0x69, 0x50, 0x6A, 0x50, 0x6B, 0x50, 0x6C, 0x50, 
-	0x6D, 0x50, 0x6E, 0x50, 0x6F, 0x50, 0x70, 0x50, 0x71, 0x50, 0x72, 0x50, 0x73, 0x50, 0x74, 0x50, 0x75, 0x50, 
-	0x76, 0x50, 0x77, 0x50, 0x78, 0x50, 0x79, 0x50, 0x7A, 0x50, 0x7B, 0x50, 0x7C, 0x50, 0x7D, 0x50, 0x7E, 0x50, 
-	0x7F, 0x50, 0x80, 0x50, 0x81, 0x50, 0x82, 0x50, 0x83, 0x50, 0x84, 0x50, 0x85, 0x50, 0x86, 0x50, 0x87, 0x50, 
-	0x88, 0x50, 0x89, 0x50, 0x8A, 0x50, 0x8B, 0x50, 0x8C, 0x50, 0x8D, 0x50, 0x8E, 0x50, 0x8F, 0x50, 0x90, 0x50, 
-	0x91, 0x50, 0x92, 0x50, 0x93, 0x50, 0x94, 0x50, 0x95, 0x50, 0x96, 0x50, 0x97, 0x50, 0x98, 0x50, 0x99, 0x50, 
-	0x9A, 0x50, 0x9B, 0x50, 0x9C, 0x50, 0x9D, 0x50, 0x9E, 0x50, 0x9F, 0x50, 0xFA, 0x40, 0xFB, 0x40, 0xFC, 0x40, 
-	0xFD, 0x40, 0xFE, 0x40, 0xFF, 0x40, 0x00, 0xC0, 0x01, 0x40, 0x02, 0x40, 0x03, 0x40, 0x04, 0x40, 0x05, 0x40, 
-	0x06, 0x40, 0x07, 0x40, 0x08, 0x40, 0x09, 0x40, 0x0A, 0x40, 0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x40, 0x0E, 0x40, 
-	0x0F, 0x40, 0x10, 0x40, 0x11, 0x40, 0x12, 0x40, 0x13, 0x40, 0x14, 0x40, 0x15, 0x40, 0x16, 0x40, 0x17, 0x40, 
-	0x18, 0x40, 0x19, 0x40, 0x1A, 0x40, 0x1B, 0x40, 0x1C, 0x40, 0x1D, 0x40, 0x1E, 0x40, 0x1F, 0x40, 0x20, 0x40, 
-	0x21, 0x40, 0x22, 0x40, 0x23, 0x40, 0x24, 0x40, 0x25, 0x40, 0x26, 0x40, 0x27, 0x40, 0x28, 0x40, 0x29, 0x40, 
-	0x2A, 0x40, 0x2B, 0x40, 0x2C, 0x40, 0x2D, 0x40, 0x2E, 0x40, 0x2F, 0x40, 0x30, 0x40, 0x31, 0x40, 0x32, 0x40, 
-	0x33, 0x40, 0x34, 0x40, 0x35, 0x40, 0x36, 0x40, 0x37, 0x40, 0x38, 0x40, 0x39, 0x40, 0x3A, 0x40, 0x3B, 0x40, 
-	0x3C, 0x40, 0x3D, 0x40, 0x3E, 0x40, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x40, 0x42, 0x40, 0x43, 0x40, 0x44, 0x40, 
-	0x45, 0x40, 0x46, 0x40, 0x47, 0x40, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x40, 0x4B, 0x40, 0x4C, 0x40, 0x4D, 0x40, 
-	0x4E, 0x40, 0x4F, 0x40, 0x50, 0x40, 0x51, 0x40, 0x52, 0x40, 0x53, 0x40, 0x54, 0x40, 0x55, 0x40, 0x56, 0x40, 
-	0x57, 0x40, 0x58, 0x40, 0x59, 0x40, 0x5A, 0x40, 0x5B, 0x40, 0x5C, 0x40, 0x5D, 0x40, 0x5E, 0x40, 0x5F, 0x40, 
-	0x60, 0x40, 0x61, 0x40, 0x62, 0x40, 0x63, 0x40, 0x64, 0x40, 0x65, 0x40, 0x66, 0x40, 0x67, 0x40, 0x68, 0x40, 
-	0x69, 0x40, 0x6A, 0x40, 0x6B, 0x40, 0x6C, 0x40, 0x6D, 0x40, 0x6E, 0x40, 0x6F, 0x40, 0x70, 0x40, 0x71, 0x40, 
-	0x72, 0x40, 0x73, 0x40, 0x74, 0x40, 0x75, 0x40, 0x76, 0x40, 0x77, 0x40, 0x78, 0x40, 0x79, 0x40, 0x7A, 0x40, 
-	0x7B, 0x40, 0x7C, 0x40, 0x7D, 0x40, 0x7E, 0x40, 0x7F, 0x40, 0x80, 0x40, 0x81, 0x40, 0x82, 0x40, 0x83, 0x40, 
-	0x84, 0x40, 0x85, 0x40, 0x86, 0x40, 0x87, 0x40, 0x88, 0x40, 0x89, 0x40, 0x8A, 0x40, 0x8B, 0x40, 0x8C, 0x40, 
-	0x8D, 0x40, 0x8E, 0x40, 0x8F, 0x40, 0x90, 0x40, 0x91, 0x40, 0x92, 0x40, 0x93, 0x40, 0x94, 0x40, 0x95, 0x40, 
-	0x96, 0x40, 0x97, 0x40, 0x98, 0x40, 0x99, 0x40, 0x9A, 0x40, 0x9B, 0x40, 0x9C, 0x40, 0x9D, 0x40, 0x9E, 0x40, 
-	0x9F, 0x40, 0xA0, 0x40, 0xA1, 0x40, 0xA2, 0x40, 0xA3, 0x40, 0xA4, 0x40, 0xA5, 0x40, 0xA6, 0x40, 0xA7, 0x40, 
-	0xA8, 0x40, 0xA9, 0x40, 0xAA, 0x40, 0xAB, 0x40, 0xAC, 0x40, 0xAD, 0x40, 0xAE, 0x40, 0xAF, 0x40, 0xB0, 0x40, 
-	0xB1, 0x40, 0xB2, 0x40, 0xB3, 0x40, 0xB4, 0x40, 0xB5, 0x40, 0xB6, 0x40, 0xB7, 0x40, 0xB8, 0x40, 0xB9, 0x40, 
-	0xBA, 0x40, 0xBB, 0x40, 0xBC, 0x40, 0xBD, 0x40, 0xBE, 0x40, 0xBF, 0x40, 0xC0, 0x40, 0xC1, 0x40, 0xC2, 0x40, 
-	0xC3, 0x40, 0xC4, 0x40, 0xC5, 0x40, 0xC6, 0x40, 0xC7, 0x40, 0xC8, 0x40, 0xC9, 0x40, 0xCA, 0x40, 0xCB, 0x40, 
-	0xCC, 0x40, 0xCD, 0x40, 0xCE, 0x40, 0xCF, 0x40, 0xD0, 0x40, 0xD1, 0x40, 0xD2, 0x40, 0xD3, 0x40, 0xD4, 0x40, 
-	0xD5, 0x40, 0xD6, 0x40, 0xD7, 0x40, 0xD8, 0x40, 0xD9, 0x40, 0xDA, 0x40, 0xDB, 0x40, 0xDC, 0x40, 0xDD, 0x40, 
-	0xDE, 0x40, 0xDF, 0x40, 0xE0, 0x40, 0xE1, 0x40, 0xE2, 0x40, 0xE3, 0x40, 0xE4, 0x40, 0xE5, 0x40, 0xE6, 0x40, 
-	0xE7, 0x40, 0xE8, 0x40, 0xE9, 0x40, 0xEA, 0x40, 0xEB, 0x40, 0xEC, 0x40, 0xED, 0x40, 0xEE, 0x40, 0xEF, 0x40, 
-	0xF0, 0x40, 0xF1, 0x40, 0xF2, 0x40, 0xF3, 0x40, 0xF4, 0x40, 0xF5, 0x40, 0xF6, 0x40, 0xF7, 0x40, 0xF8, 0x40, 
-	0xF9, 0x40, 0x9A, 0x50, 0x9B, 0x50, 0x9C, 0x50, 0x9D, 0x50, 0x9E, 0x50, 0x9F, 0x50, 0xA0, 0x50, 0xA1, 0x50, 
-	0xA2, 0x50, 0xA3, 0x50, 0xA4, 0x50, 0xA5, 0x50, 0xA6, 0x50, 0xA7, 0x50, 0xA8, 0x50, 0xA9, 0x50, 0xAA, 0x50, 
-	0xAB, 0x50, 0xAC, 0x50, 0xAD, 0x50, 0xAE, 0x50, 0xAF, 0x50, 0xB0, 0x50, 0xB1, 0x50, 0xB2, 0x50, 0xB3, 0x50, 
-	0xB4, 0x50, 0xB5, 0x50, 0xB6, 0x50, 0xB7, 0x50, 0xB8, 0x50, 0xB9, 0x50, 0xBA, 0x50, 0xBB, 0x50, 0xBC, 0x50, 
-	0xBD, 0x50, 0xBE, 0x50, 0xBF, 0x50, 0xC0, 0x50, 0xC1, 0x50, 0xC2, 0x50, 0xC3, 0x50, 0xC4, 0x50, 0xC5, 0x50, 
-	0xC6, 0x50, 0xC7, 0x50, 0xC8, 0x50, 0xC9, 0x50, 0xCA, 0x50, 0xCB, 0x50, 0xCC, 0x50, 0xCD, 0x50, 0xCE, 0x50, 
-	0xCF, 0x50, 0xD0, 0x50, 0xD1, 0x50, 0xD2, 0x50, 0xD3, 0x50, 0xD4, 0x50, 0xD5, 0x50, 0xD6, 0x50, 0xD7, 0x50, 
-	0xD8, 0x50, 0xD9, 0x50, 0xDA, 0x50, 0xDB, 0x50, 0xDC, 0x50, 0xDD, 0x50, 0xDE, 0x50, 0xDF, 0x50, 0xE0, 0x50, 
-	0xE1, 0x50, 0xE2, 0x50, 0xE3, 0x50, 0xE4, 0x50, 0xE5, 0x50, 0xE6, 0x50, 0xE7, 0x50, 0xE8, 0x50, 0xE9, 0x50, 
-	0xEA, 0x50, 0xEB, 0x50, 0xEC, 0x50, 0xED, 0x50, 0xEE, 0x50, 0xEF, 0x50, 0xF0, 0x50, 0xF1, 0x50, 0xF2, 0x50, 
-	0xF3, 0x50, 0xF4, 0x50, 0xF5, 0x50, 0xF6, 0x50, 0xF7, 0x50, 0xF8, 0x50, 0xF9, 0x50, 0xFA, 0x50, 0xFB, 0x50, 
-	0xFC, 0x50, 0xFD, 0x50, 0xFE, 0x50, 0xFF, 0x50, 0x00, 0xD0, 0x01, 0x50, 0x02, 0x50, 0x03, 0x50, 0x04, 0x50, 
-	0x05, 0x50, 0x06, 0x50, 0x07, 0x50, 0x08, 0x50, 0x09, 0x50, 0x0A, 0x50, 0x0B, 0x50, 0x0C, 0x50, 0x0D, 0x50, 
-	0x0E, 0x50, 0x0F, 0x50, 0x10, 0x50, 0x11, 0x50, 0x12, 0x50, 0x13, 0x50, 0x14, 0x50, 0x15, 0x50, 0x16, 0x50, 
-	0x17, 0x50, 0x18, 0x50, 0x19, 0x50, 0x1A, 0x50, 0x1B, 0x50, 0x1C, 0x50, 0x1D, 0x50, 0x1E, 0x50, 0x1F, 0x50, 
-	0x20, 0x50, 0x21, 0x50, 0x22, 0x50, 0x23, 0x50, 0x24, 0x50, 0x25, 0x50, 0x26, 0x50, 0x27, 0x50, 0x28, 0x50, 
-	0x29, 0x50, 0x2A, 0x50, 0x2B, 0x50, 0x2C, 0x50, 0x2D, 0x50, 0x2E, 0x50, 0x2F, 0x50, 0x30, 0x50, 0x31, 0x50, 
-	0x32, 0x50, 0x33, 0x50, 0x34, 0x50, 0x35, 0x50, 0x36, 0x50, 0x37, 0x50, 0x38, 0x50, 0x39, 0x50, 0x3A, 0x50, 
-	0x3B, 0x50, 0x3C, 0x50, 0x3D, 0x50, 0x3E, 0x50, 0x3F, 0x50, 0x40, 0x50, 0x41, 0x50, 0x42, 0x50, 0x43, 0x50, 
-	0x44, 0x50, 0x45, 0x50, 0x46, 0x50, 0x47, 0x50, 0x48, 0x50, 0x49, 0x50, 0x4A, 0x50, 0x4B, 0x50, 0x4C, 0x50, 
-	0x4D, 0x50, 0x4E, 0x50, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x50, 0x52, 0x50, 0x53, 0x50, 0x54, 0x50, 0x55, 0x50, 
-	0x56, 0x50, 0x57, 0x50, 0x58, 0x50, 0x59, 0x50, 0x5A, 0x50, 0x5B, 0x50, 0x5C, 0x50, 0x5D, 0x50, 0x5E, 0x50, 
-	0x5F, 0x50, 0x60, 0x50, 0x61, 0x50, 0x62, 0x50, 0x63, 0x50, 0x64, 0x50, 0x65, 0x50, 0x66, 0x50, 0x67, 0x50, 
-	0x68, 0x50, 0x69, 0x50, 0x6A, 0x50, 0x6B, 0x50, 0x6C, 0x50, 0x6D, 0x50, 0x6E, 0x50, 0x6F, 0x50, 0x70, 0x50, 
-	0x71, 0x50, 0x72, 0x50, 0x73, 0x50, 0x74, 0x50, 0x75, 0x50, 0x76, 0x50, 0x77, 0x50, 0x78, 0x50, 0x79, 0x50, 
-	0x7A, 0x50, 0x7B, 0x50, 0x7C, 0x50, 0x7D, 0x50, 0x7E, 0x50, 0x7F, 0x50, 0x80, 0x50, 0x81, 0x50, 0x82, 0x50, 
-	0x83, 0x50, 0x84, 0x50, 0x85, 0x50, 0x86, 0x50, 0x87, 0x50, 0x88, 0x50, 0x89, 0x50, 0x8A, 0x50, 0x8B, 0x50, 
-	0x8C, 0x50, 0x8D, 0x50, 0x8E, 0x50, 0x8F, 0x50, 0x90, 0x50, 0x91, 0x50, 0x92, 0x50, 0x93, 0x50, 0x94, 0x50, 
-	0x95, 0x50, 0x96, 0x50, 0x97, 0x50, 0x98, 0x50, 0x99, 0x50, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 
-	0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 
-	0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 
-	0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 
-	0x25, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 
-	0x28, 0x00, 0x29, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x30, 0x00, 
-	0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 
-	0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 
-	0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x50, 0x00, 0x51, 0x00, 
-	0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 
-	0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 
-	0x64, 0x00, 0x65, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x66, 0x00, 
-	0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 
-	0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 0x77, 0x00, 0x78, 0x00, 
-	0x79, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x80, 0x00, 0x81, 0x00, 
-	0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x90, 0x00, 
-	0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 
-	0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 
-	0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 
-	0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 
-	0x15, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 
-	0x18, 0x10, 0x19, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x20, 0x10, 
-	0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 
-	0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 
-	0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x40, 0x10, 0x41, 0x10, 
-	0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 
-	0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 
-	0x54, 0x10, 0x55, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 
-	0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 
-	0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x66, 0x10, 0x67, 0x10, 0x68, 0x10, 
-	0x69, 0x10, 0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 0x75, 0x10, 0x70, 0x10, 0x71, 0x10, 
-	0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 0x75, 0x10, 0x76, 0x10, 0x77, 0x10, 0x78, 0x10, 0x79, 0x10, 0x80, 0x10, 
-	0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 0x80, 0x10, 0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 
-	0x84, 0x10, 0x85, 0x10, 0x86, 0x10, 0x87, 0x10, 0x88, 0x10, 0x89, 0x10, 0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 
-	0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 
-	0x96, 0x10, 0x97, 0x10, 0x98, 0x10, 0x99, 0x10, 0xA0, 0x10, 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 
-	0xA5, 0x10, 0xA0, 0x10, 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 
-	0xA8, 0x10, 0xA9, 0x10, 0xB0, 0x10, 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB0, 0x10, 
-	0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, 0xB9, 0x10, 
-	0xC0, 0x10, 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xC0, 0x10, 0xC1, 0x10, 0xC2, 0x10, 
-	0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xC6, 0x10, 0xC7, 0x10, 0xC8, 0x10, 0xC9, 0x10, 0xD0, 0x10, 0xD1, 0x10, 
-	0xD2, 0x10, 0xD3, 0x10, 0xD4, 0x10, 0xD5, 0x10, 0xD0, 0x10, 0xD1, 0x10, 0xD2, 0x10, 0xD3, 0x10, 0xD4, 0x10, 
-	0xD5, 0x10, 0xD6, 0x10, 0xD7, 0x10, 0xD8, 0x10, 0xD9, 0x10, 0xE0, 0x10, 0xE1, 0x10, 0xE2, 0x10, 0xE3, 0x10, 
-	0xE4, 0x10, 0xE5, 0x10, 0xE0, 0x10, 0xE1, 0x10, 0xE2, 0x10, 0xE3, 0x10, 0xE4, 0x10, 0xE5, 0x10, 0xE6, 0x10, 
-	0xE7, 0x10, 0xE8, 0x10, 0xE9, 0x10, 0xF0, 0x10, 0xF1, 0x10, 0xF2, 0x10, 0xF3, 0x10, 0xF4, 0x10, 0xF5, 0x10, 
-	0xF0, 0x10, 0xF1, 0x10, 0xF2, 0x10, 0xF3, 0x10, 0xF4, 0x10, 0xF5, 0x10, 0xF6, 0x10, 0xF7, 0x10, 0xF8, 0x10, 
-	0xF9, 0x10, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x00, 0x90, 0x01, 0x10, 
-	0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x10, 0x10, 
-	0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 
-	0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 
-	0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 
-	0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 
-	0x35, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 
-	0x38, 0x10, 0x39, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x40, 0x10, 
-	0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 
-	0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 
-	0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x60, 0x10, 0x61, 0x10, 
-	0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 
-	0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 
-	0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 
-	0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 
-	0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 
-	0x2F, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 
-	0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x40, 0x00, 
-	0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 
-	0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 
-	0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 
-	0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 
-	0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B, 0x00, 0x6C, 0x00, 0x6D, 0x00, 
-	0x6E, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 
-	0x77, 0x00, 0x78, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, 
-	0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 
-	0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, 0x90, 0x00, 0x91, 0x00, 
-	0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 
-	0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, 0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 
-	0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x0A, 0x10, 0x0B, 0x10, 0x0C, 0x10, 
-	0x0D, 0x10, 0x0E, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 
-	0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x1A, 0x10, 0x1B, 0x10, 0x1C, 0x10, 0x1D, 0x10, 0x1E, 0x10, 
-	0x1F, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 
-	0x28, 0x10, 0x29, 0x10, 0x2A, 0x10, 0x2B, 0x10, 0x2C, 0x10, 0x2D, 0x10, 0x2E, 0x10, 0x2F, 0x10, 0x30, 0x10, 
-	0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 
-	0x3A, 0x10, 0x3B, 0x10, 0x3C, 0x10, 0x3D, 0x10, 0x3E, 0x10, 0x3F, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 
-	0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 0x4A, 0x10, 0x4B, 0x10, 
-	0x4C, 0x10, 0x4D, 0x10, 0x4E, 0x10, 0x4F, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 
-	0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x5A, 0x10, 0x5B, 0x10, 0x5C, 0x10, 0x5D, 0x10, 
-	0x5E, 0x10, 0x5F, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x66, 0x10, 
-	0x67, 0x10, 0x68, 0x10, 0x69, 0x10, 0x6A, 0x10, 0x6B, 0x10, 0x6C, 0x10, 0x6D, 0x10, 0x6E, 0x10, 0x6F, 0x10, 
-	0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 0x75, 0x10, 0x76, 0x10, 0x77, 0x10, 0x78, 0x10, 
-	0x79, 0x10, 0x7A, 0x10, 0x7B, 0x10, 0x7C, 0x10, 0x7D, 0x10, 0x7E, 0x10, 0x7F, 0x10, 0x80, 0x10, 0x81, 0x10, 
-	0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 0x86, 0x10, 0x87, 0x10, 0x88, 0x10, 0x89, 0x10, 0x8A, 0x10, 
-	0x8B, 0x10, 0x8C, 0x10, 0x8D, 0x10, 0x8E, 0x10, 0x8F, 0x10, 0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 0x93, 0x10, 
-	0x94, 0x10, 0x95, 0x10, 0x96, 0x10, 0x97, 0x10, 0x98, 0x10, 0x99, 0x10, 0x9A, 0x10, 0x9B, 0x10, 0x9C, 0x10, 
-	0x9D, 0x10, 0x9E, 0x10, 0x9F, 0x10, 0xA0, 0x10, 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 
-	0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 
-	0xAF, 0x10, 0xB0, 0x10, 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 
-	0xB8, 0x10, 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, 
-	0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xC6, 0x10, 0xC7, 0x10, 0xC8, 0x10, 0xC9, 0x10, 
-	0xCA, 0x10, 0xCB, 0x10, 0xCC, 0x10, 0xCD, 0x10, 0xCE, 0x10, 0xCF, 0x10, 0xD0, 0x10, 0xD1, 0x10, 0xD2, 0x10, 
-	0xD3, 0x10, 0xD4, 0x10, 0xD5, 0x10, 0xD6, 0x10, 0xD7, 0x10, 0xD8, 0x10, 0xD9, 0x10, 0xDA, 0x10, 0xDB, 0x10, 
-	0xDC, 0x10, 0xDD, 0x10, 0xDE, 0x10, 0xDF, 0x10, 0xE0, 0x10, 0xE1, 0x10, 0xE2, 0x10, 0xE3, 0x10, 0xE4, 0x10, 
-	0xE5, 0x10, 0xE6, 0x10, 0xE7, 0x10, 0xE8, 0x10, 0xE9, 0x10, 0xEA, 0x10, 0xEB, 0x10, 0xEC, 0x10, 0xED, 0x10, 
-	0xEE, 0x10, 0xEF, 0x10, 0xF0, 0x10, 0xF1, 0x10, 0xF2, 0x10, 0xF3, 0x10, 0xF4, 0x10, 0xF5, 0x10, 0xF6, 0x10, 
-	0xF7, 0x10, 0xF8, 0x10, 0xF9, 0x10, 0xFA, 0x10, 0xFB, 0x10, 0xFC, 0x10, 0xFD, 0x10, 0xFE, 0x10, 0xFF, 0x10, 
-	0x00, 0x90, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 
-	0x09, 0x10, 0x0A, 0x10, 0x0B, 0x10, 0x0C, 0x10, 0x0D, 0x10, 0x0E, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x10, 
-	0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x1A, 0x10, 
-	0x1B, 0x10, 0x1C, 0x10, 0x1D, 0x10, 0x1E, 0x10, 0x1F, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 
-	0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x2A, 0x10, 0x2B, 0x10, 0x2C, 0x10, 
-	0x2D, 0x10, 0x2E, 0x10, 0x2F, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 
-	0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x3A, 0x10, 0x3B, 0x10, 0x3C, 0x10, 0x3D, 0x10, 0x3E, 0x10, 
-	0x3F, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 
-	0x48, 0x10, 0x49, 0x10, 0x4A, 0x10, 0x4B, 0x10, 0x4C, 0x10, 0x4D, 0x10, 0x4E, 0x10, 0x4F, 0x10, 0x50, 0x10, 
-	0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 
-	0x5A, 0x10, 0x5B, 0x10, 0x5C, 0x10, 0x5D, 0x10, 0x5E, 0x10, 0x5F, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 
-	0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x00, 0xC0, 0x01, 0x40, 0x02, 0x40, 0x03, 0x40, 0x04, 0x40, 0x05, 0x40, 
-	0x06, 0x40, 0x07, 0x40, 0x08, 0x40, 0x09, 0x40, 0x0A, 0x40, 0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x40, 0x0E, 0x40, 
-	0x0F, 0x40, 0x10, 0x40, 0x11, 0x40, 0x12, 0x40, 0x13, 0x40, 0x14, 0x40, 0x15, 0x40, 0x16, 0x40, 0x17, 0x40, 
-	0x18, 0x40, 0x19, 0x40, 0x1A, 0x40, 0x1B, 0x40, 0x1C, 0x40, 0x1D, 0x40, 0x1E, 0x40, 0x1F, 0x40, 0x20, 0x40, 
-	0x21, 0x40, 0x22, 0x40, 0x23, 0x40, 0x24, 0x40, 0x25, 0x40, 0x26, 0x40, 0x27, 0x40, 0x28, 0x40, 0x29, 0x40, 
-	0x2A, 0x40, 0x2B, 0x40, 0x2C, 0x40, 0x2D, 0x40, 0x2E, 0x40, 0x2F, 0x40, 0x30, 0x40, 0x31, 0x40, 0x32, 0x40, 
-	0x33, 0x40, 0x34, 0x40, 0x35, 0x40, 0x36, 0x40, 0x37, 0x40, 0x38, 0x40, 0x39, 0x40, 0x3A, 0x40, 0x3B, 0x40, 
-	0x3C, 0x40, 0x3D, 0x40, 0x3E, 0x40, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x40, 0x42, 0x40, 0x43, 0x40, 0x44, 0x40, 
-	0x45, 0x40, 0x46, 0x40, 0x47, 0x40, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x40, 0x4B, 0x40, 0x4C, 0x40, 0x4D, 0x40, 
-	0x4E, 0x40, 0x4F, 0x40, 0x50, 0x40, 0x51, 0x40, 0x52, 0x40, 0x53, 0x40, 0x54, 0x40, 0x55, 0x40, 0x56, 0x40, 
-	0x57, 0x40, 0x58, 0x40, 0x59, 0x40, 0x5A, 0x40, 0x5B, 0x40, 0x5C, 0x40, 0x5D, 0x40, 0x5E, 0x40, 0x5F, 0x40, 
-	0x60, 0x40, 0x61, 0x40, 0x62, 0x40, 0x63, 0x40, 0x64, 0x40, 0x65, 0x40, 0x66, 0x40, 0x67, 0x40, 0x68, 0x40, 
-	0x69, 0x40, 0x6A, 0x40, 0x6B, 0x40, 0x6C, 0x40, 0x6D, 0x40, 0x6E, 0x40, 0x6F, 0x40, 0x70, 0x40, 0x71, 0x40, 
-	0x72, 0x40, 0x73, 0x40, 0x74, 0x40, 0x75, 0x40, 0x76, 0x40, 0x77, 0x40, 0x78, 0x40, 0x79, 0x40, 0x7A, 0x40, 
-	0x7B, 0x40, 0x7C, 0x40, 0x7D, 0x40, 0x7E, 0x40, 0x7F, 0x40, 0x80, 0x40, 0x81, 0x40, 0x82, 0x40, 0x83, 0x40, 
-	0x84, 0x40, 0x85, 0x40, 0x86, 0x40, 0x87, 0x40, 0x88, 0x40, 0x89, 0x40, 0x8A, 0x40, 0x8B, 0x40, 0x8C, 0x40, 
-	0x8D, 0x40, 0x8E, 0x40, 0x8F, 0x40, 0x90, 0x40, 0x91, 0x40, 0x92, 0x40, 0x93, 0x40, 0x94, 0x40, 0x95, 0x40, 
-	0x96, 0x40, 0x97, 0x40, 0x98, 0x40, 0x99, 0x40, 0x9A, 0x40, 0x9B, 0x40, 0x9C, 0x40, 0x9D, 0x40, 0x9E, 0x40, 
-	0x9F, 0x40, 0xA0, 0x40, 0xA1, 0x40, 0xA2, 0x40, 0xA3, 0x40, 0xA4, 0x40, 0xA5, 0x40, 0xA6, 0x40, 0xA7, 0x40, 
-	0xA8, 0x40, 0xA9, 0x40, 0xAA, 0x40, 0xAB, 0x40, 0xAC, 0x40, 0xAD, 0x40, 0xAE, 0x40, 0xAF, 0x40, 0xB0, 0x40, 
-	0xB1, 0x40, 0xB2, 0x40, 0xB3, 0x40, 0xB4, 0x40, 0xB5, 0x40, 0xB6, 0x40, 0xB7, 0x40, 0xB8, 0x40, 0xB9, 0x40, 
-	0xBA, 0x40, 0xBB, 0x40, 0xBC, 0x40, 0xBD, 0x40, 0xBE, 0x40, 0xBF, 0x40, 0xC0, 0x40, 0xC1, 0x40, 0xC2, 0x40, 
-	0xC3, 0x40, 0xC4, 0x40, 0xC5, 0x40, 0xC6, 0x40, 0xC7, 0x40, 0xC8, 0x40, 0xC9, 0x40, 0xCA, 0x40, 0xCB, 0x40, 
-	0xCC, 0x40, 0xCD, 0x40, 0xCE, 0x40, 0xCF, 0x40, 0xD0, 0x40, 0xD1, 0x40, 0xD2, 0x40, 0xD3, 0x40, 0xD4, 0x40, 
-	0xD5, 0x40, 0xD6, 0x40, 0xD7, 0x40, 0xD8, 0x40, 0xD9, 0x40, 0xDA, 0x40, 0xDB, 0x40, 0xDC, 0x40, 0xDD, 0x40, 
-	0xDE, 0x40, 0xDF, 0x40, 0xE0, 0x40, 0xE1, 0x40, 0xE2, 0x40, 0xE3, 0x40, 0xE4, 0x40, 0xE5, 0x40, 0xE6, 0x40, 
-	0xE7, 0x40, 0xE8, 0x40, 0xE9, 0x40, 0xEA, 0x40, 0xEB, 0x40, 0xEC, 0x40, 0xED, 0x40, 0xEE, 0x40, 0xEF, 0x40, 
-	0xF0, 0x40, 0xF1, 0x40, 0xF2, 0x40, 0xF3, 0x40, 0xF4, 0x40, 0xF5, 0x40, 0xF6, 0x40, 0xF7, 0x40, 0xF8, 0x40, 
-	0xF9, 0x40, 0xFA, 0x40, 0xFB, 0x40, 0xFC, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFF, 0x40, 0xA0, 0x50, 0xA1, 0x50, 
-	0xA2, 0x50, 0xA3, 0x50, 0xA4, 0x50, 0xA5, 0x50, 0xA6, 0x50, 0xA7, 0x50, 0xA8, 0x50, 0xA9, 0x50, 0xAA, 0x50, 
-	0xAB, 0x50, 0xAC, 0x50, 0xAD, 0x50, 0xAE, 0x50, 0xAF, 0x50, 0xB0, 0x50, 0xB1, 0x50, 0xB2, 0x50, 0xB3, 0x50, 
-	0xB4, 0x50, 0xB5, 0x50, 0xB6, 0x50, 0xB7, 0x50, 0xB8, 0x50, 0xB9, 0x50, 0xBA, 0x50, 0xBB, 0x50, 0xBC, 0x50, 
-	0xBD, 0x50, 0xBE, 0x50, 0xBF, 0x50, 0xC0, 0x50, 0xC1, 0x50, 0xC2, 0x50, 0xC3, 0x50, 0xC4, 0x50, 0xC5, 0x50, 
-	0xC6, 0x50, 0xC7, 0x50, 0xC8, 0x50, 0xC9, 0x50, 0xCA, 0x50, 0xCB, 0x50, 0xCC, 0x50, 0xCD, 0x50, 0xCE, 0x50, 
-	0xCF, 0x50, 0xD0, 0x50, 0xD1, 0x50, 0xD2, 0x50, 0xD3, 0x50, 0xD4, 0x50, 0xD5, 0x50, 0xD6, 0x50, 0xD7, 0x50, 
-	0xD8, 0x50, 0xD9, 0x50, 0xDA, 0x50, 0xDB, 0x50, 0xDC, 0x50, 0xDD, 0x50, 0xDE, 0x50, 0xDF, 0x50, 0xE0, 0x50, 
-	0xE1, 0x50, 0xE2, 0x50, 0xE3, 0x50, 0xE4, 0x50, 0xE5, 0x50, 0xE6, 0x50, 0xE7, 0x50, 0xE8, 0x50, 0xE9, 0x50, 
-	0xEA, 0x50, 0xEB, 0x50, 0xEC, 0x50, 0xED, 0x50, 0xEE, 0x50, 0xEF, 0x50, 0xF0, 0x50, 0xF1, 0x50, 0xF2, 0x50, 
-	0xF3, 0x50, 0xF4, 0x50, 0xF5, 0x50, 0xF6, 0x50, 0xF7, 0x50, 0xF8, 0x50, 0xF9, 0x50, 0xFA, 0x50, 0xFB, 0x50, 
-	0xFC, 0x50, 0xFD, 0x50, 0xFE, 0x50, 0xFF, 0x50, 0x00, 0xD0, 0x01, 0x50, 0x02, 0x50, 0x03, 0x50, 0x04, 0x50, 
-	0x05, 0x50, 0x06, 0x50, 0x07, 0x50, 0x08, 0x50, 0x09, 0x50, 0x0A, 0x50, 0x0B, 0x50, 0x0C, 0x50, 0x0D, 0x50, 
-	0x0E, 0x50, 0x0F, 0x50, 0x10, 0x50, 0x11, 0x50, 0x12, 0x50, 0x13, 0x50, 0x14, 0x50, 0x15, 0x50, 0x16, 0x50, 
-	0x17, 0x50, 0x18, 0x50, 0x19, 0x50, 0x1A, 0x50, 0x1B, 0x50, 0x1C, 0x50, 0x1D, 0x50, 0x1E, 0x50, 0x1F, 0x50, 
-	0x20, 0x50, 0x21, 0x50, 0x22, 0x50, 0x23, 0x50, 0x24, 0x50, 0x25, 0x50, 0x26, 0x50, 0x27, 0x50, 0x28, 0x50, 
-	0x29, 0x50, 0x2A, 0x50, 0x2B, 0x50, 0x2C, 0x50, 0x2D, 0x50, 0x2E, 0x50, 0x2F, 0x50, 0x30, 0x50, 0x31, 0x50, 
-	0x32, 0x50, 0x33, 0x50, 0x34, 0x50, 0x35, 0x50, 0x36, 0x50, 0x37, 0x50, 0x38, 0x50, 0x39, 0x50, 0x3A, 0x50, 
-	0x3B, 0x50, 0x3C, 0x50, 0x3D, 0x50, 0x3E, 0x50, 0x3F, 0x50, 0x40, 0x50, 0x41, 0x50, 0x42, 0x50, 0x43, 0x50, 
-	0x44, 0x50, 0x45, 0x50, 0x46, 0x50, 0x47, 0x50, 0x48, 0x50, 0x49, 0x50, 0x4A, 0x50, 0x4B, 0x50, 0x4C, 0x50, 
-	0x4D, 0x50, 0x4E, 0x50, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x50, 0x52, 0x50, 0x53, 0x50, 0x54, 0x50, 0x55, 0x50, 
-	0x56, 0x50, 0x57, 0x50, 0x58, 0x50, 0x59, 0x50, 0x5A, 0x50, 0x5B, 0x50, 0x5C, 0x50, 0x5D, 0x50, 0x5E, 0x50, 
-	0x5F, 0x50, 0x60, 0x50, 0x61, 0x50, 0x62, 0x50, 0x63, 0x50, 0x64, 0x50, 0x65, 0x50, 0x66, 0x50, 0x67, 0x50, 
-	0x68, 0x50, 0x69, 0x50, 0x6A, 0x50, 0x6B, 0x50, 0x6C, 0x50, 0x6D, 0x50, 0x6E, 0x50, 0x6F, 0x50, 0x70, 0x50, 
-	0x71, 0x50, 0x72, 0x50, 0x73, 0x50, 0x74, 0x50, 0x75, 0x50, 0x76, 0x50, 0x77, 0x50, 0x78, 0x50, 0x79, 0x50, 
-	0x7A, 0x50, 0x7B, 0x50, 0x7C, 0x50, 0x7D, 0x50, 0x7E, 0x50, 0x7F, 0x50, 0x80, 0x50, 0x81, 0x50, 0x82, 0x50, 
-	0x83, 0x50, 0x84, 0x50, 0x85, 0x50, 0x86, 0x50, 0x87, 0x50, 0x88, 0x50, 0x89, 0x50, 0x8A, 0x50, 0x8B, 0x50, 
-	0x8C, 0x50, 0x8D, 0x50, 0x8E, 0x50, 0x8F, 0x50, 0x90, 0x50, 0x91, 0x50, 0x92, 0x50, 0x93, 0x50, 0x94, 0x50, 
-	0x95, 0x50, 0x96, 0x50, 0x97, 0x50, 0x98, 0x50, 0x99, 0x50, 0x9A, 0x50, 0x9B, 0x50, 0x9C, 0x50, 0x9D, 0x50, 
-	0x9E, 0x50, 0x9F, 0x50, 0xFA, 0x40, 0xFB, 0x40, 0xFC, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFF, 0x40, 0x00, 0xC0, 
-	0x01, 0x40, 0x02, 0x40, 0x03, 0x40, 0x04, 0x40, 0x05, 0x40, 0x06, 0x40, 0x07, 0x40, 0x08, 0x40, 0x09, 0x40, 
-	0x0A, 0x40, 0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x40, 0x0E, 0x40, 0x0F, 0x40, 0x10, 0x40, 0x11, 0x40, 0x12, 0x40, 
-	0x13, 0x40, 0x14, 0x40, 0x15, 0x40, 0x16, 0x40, 0x17, 0x40, 0x18, 0x40, 0x19, 0x40, 0x1A, 0x40, 0x1B, 0x40, 
-	0x1C, 0x40, 0x1D, 0x40, 0x1E, 0x40, 0x1F, 0x40, 0x20, 0x40, 0x21, 0x40, 0x22, 0x40, 0x23, 0x40, 0x24, 0x40, 
-	0x25, 0x40, 0x26, 0x40, 0x27, 0x40, 0x28, 0x40, 0x29, 0x40, 0x2A, 0x40, 0x2B, 0x40, 0x2C, 0x40, 0x2D, 0x40, 
-	0x2E, 0x40, 0x2F, 0x40, 0x30, 0x40, 0x31, 0x40, 0x32, 0x40, 0x33, 0x40, 0x34, 0x40, 0x35, 0x40, 0x36, 0x40, 
-	0x37, 0x40, 0x38, 0x40, 0x39, 0x40, 0x3A, 0x40, 0x3B, 0x40, 0x3C, 0x40, 0x3D, 0x40, 0x3E, 0x40, 0x3F, 0x40, 
-	0x40, 0x40, 0x41, 0x40, 0x42, 0x40, 0x43, 0x40, 0x44, 0x40, 0x45, 0x40, 0x46, 0x40, 0x47, 0x40, 0x48, 0x40, 
-	0x49, 0x40, 0x4A, 0x40, 0x4B, 0x40, 0x4C, 0x40, 0x4D, 0x40, 0x4E, 0x40, 0x4F, 0x40, 0x50, 0x40, 0x51, 0x40, 
-	0x52, 0x40, 0x53, 0x40, 0x54, 0x40, 0x55, 0x40, 0x56, 0x40, 0x57, 0x40, 0x58, 0x40, 0x59, 0x40, 0x5A, 0x40, 
-	0x5B, 0x40, 0x5C, 0x40, 0x5D, 0x40, 0x5E, 0x40, 0x5F, 0x40, 0x60, 0x40, 0x61, 0x40, 0x62, 0x40, 0x63, 0x40, 
-	0x64, 0x40, 0x65, 0x40, 0x66, 0x40, 0x67, 0x40, 0x68, 0x40, 0x69, 0x40, 0x6A, 0x40, 0x6B, 0x40, 0x6C, 0x40, 
-	0x6D, 0x40, 0x6E, 0x40, 0x6F, 0x40, 0x70, 0x40, 0x71, 0x40, 0x72, 0x40, 0x73, 0x40, 0x74, 0x40, 0x75, 0x40, 
-	0x76, 0x40, 0x77, 0x40, 0x78, 0x40, 0x79, 0x40, 0x7A, 0x40, 0x7B, 0x40, 0x7C, 0x40, 0x7D, 0x40, 0x7E, 0x40, 
-	0x7F, 0x40, 0x80, 0x40, 0x81, 0x40, 0x82, 0x40, 0x83, 0x40, 0x84, 0x40, 0x85, 0x40, 0x86, 0x40, 0x87, 0x40, 
-	0x88, 0x40, 0x89, 0x40, 0x8A, 0x40, 0x8B, 0x40, 0x8C, 0x40, 0x8D, 0x40, 0x8E, 0x40, 0x8F, 0x40, 0x90, 0x40, 
-	0x91, 0x40, 0x92, 0x40, 0x93, 0x40, 0x94, 0x40, 0x95, 0x40, 0x96, 0x40, 0x97, 0x40, 0x98, 0x40, 0x99, 0x40, 
-	0x9A, 0x40, 0x9B, 0x40, 0x9C, 0x40, 0x9D, 0x40, 0x9E, 0x40, 0x9F, 0x40, 0xA0, 0x40, 0xA1, 0x40, 0xA2, 0x40, 
-	0xA3, 0x40, 0xA4, 0x40, 0xA5, 0x40, 0xA6, 0x40, 0xA7, 0x40, 0xA8, 0x40, 0xA9, 0x40, 0xAA, 0x40, 0xAB, 0x40, 
-	0xAC, 0x40, 0xAD, 0x40, 0xAE, 0x40, 0xAF, 0x40, 0xB0, 0x40, 0xB1, 0x40, 0xB2, 0x40, 0xB3, 0x40, 0xB4, 0x40, 
-	0xB5, 0x40, 0xB6, 0x40, 0xB7, 0x40, 0xB8, 0x40, 0xB9, 0x40, 0xBA, 0x40, 0xBB, 0x40, 0xBC, 0x40, 0xBD, 0x40, 
-	0xBE, 0x40, 0xBF, 0x40, 0xC0, 0x40, 0xC1, 0x40, 0xC2, 0x40, 0xC3, 0x40, 0xC4, 0x40, 0xC5, 0x40, 0xC6, 0x40, 
-	0xC7, 0x40, 0xC8, 0x40, 0xC9, 0x40, 0xCA, 0x40, 0xCB, 0x40, 0xCC, 0x40, 0xCD, 0x40, 0xCE, 0x40, 0xCF, 0x40, 
-	0xD0, 0x40, 0xD1, 0x40, 0xD2, 0x40, 0xD3, 0x40, 0xD4, 0x40, 0xD5, 0x40, 0xD6, 0x40, 0xD7, 0x40, 0xD8, 0x40, 
-	0xD9, 0x40, 0xDA, 0x40, 0xDB, 0x40, 0xDC, 0x40, 0xDD, 0x40, 0xDE, 0x40, 0xDF, 0x40, 0xE0, 0x40, 0xE1, 0x40, 
-	0xE2, 0x40, 0xE3, 0x40, 0xE4, 0x40, 0xE5, 0x40, 0xE6, 0x40, 0xE7, 0x40, 0xE8, 0x40, 0xE9, 0x40, 0xEA, 0x40, 
-	0xEB, 0x40, 0xEC, 0x40, 0xED, 0x40, 0xEE, 0x40, 0xEF, 0x40, 0xF0, 0x40, 0xF1, 0x40, 0xF2, 0x40, 0xF3, 0x40, 
-	0xF4, 0x40, 0xF5, 0x40, 0xF6, 0x40, 0xF7, 0x40, 0xF8, 0x40, 0xF9, 0x40, 0x9A, 0x50, 0x9B, 0x50, 0x9C, 0x50, 
-	0x9D, 0x50, 0x9E, 0x50, 0x9F, 0x50, 0xA0, 0x50, 0xA1, 0x50, 0xA2, 0x50, 0xA3, 0x50, 0xA4, 0x50, 0xA5, 0x50, 
-	0xA6, 0x50, 0xA7, 0x50, 0xA8, 0x50, 0xA9, 0x50, 0xAA, 0x50, 0xAB, 0x50, 0xAC, 0x50, 0xAD, 0x50, 0xAE, 0x50, 
-	0xAF, 0x50, 0xB0, 0x50, 0xB1, 0x50, 0xB2, 0x50, 0xB3, 0x50, 0xB4, 0x50, 0xB5, 0x50, 0xB6, 0x50, 0xB7, 0x50, 
-	0xB8, 0x50, 0xB9, 0x50, 0xBA, 0x50, 0xBB, 0x50, 0xBC, 0x50, 0xBD, 0x50, 0xBE, 0x50, 0xBF, 0x50, 0xC0, 0x50, 
-	0xC1, 0x50, 0xC2, 0x50, 0xC3, 0x50, 0xC4, 0x50, 0xC5, 0x50, 0xC6, 0x50, 0xC7, 0x50, 0xC8, 0x50, 0xC9, 0x50, 
-	0xCA, 0x50, 0xCB, 0x50, 0xCC, 0x50, 0xCD, 0x50, 0xCE, 0x50, 0xCF, 0x50, 0xD0, 0x50, 0xD1, 0x50, 0xD2, 0x50, 
-	0xD3, 0x50, 0xD4, 0x50, 0xD5, 0x50, 0xD6, 0x50, 0xD7, 0x50, 0xD8, 0x50, 0xD9, 0x50, 0xDA, 0x50, 0xDB, 0x50, 
-	0xDC, 0x50, 0xDD, 0x50, 0xDE, 0x50, 0xDF, 0x50, 0xE0, 0x50, 0xE1, 0x50, 0xE2, 0x50, 0xE3, 0x50, 0xE4, 0x50, 
-	0xE5, 0x50, 0xE6, 0x50, 0xE7, 0x50, 0xE8, 0x50, 0xE9, 0x50, 0xEA, 0x50, 0xEB, 0x50, 0xEC, 0x50, 0xED, 0x50, 
-	0xEE, 0x50, 0xEF, 0x50, 0xF0, 0x50, 0xF1, 0x50, 0xF2, 0x50, 0xF3, 0x50, 0xF4, 0x50, 0xF5, 0x50, 0xF6, 0x50, 
-	0xF7, 0x50, 0xF8, 0x50, 0xF9, 0x50, 0xFA, 0x50, 0xFB, 0x50, 0xFC, 0x50, 0xFD, 0x50, 0xFE, 0x50, 0xFF, 0x50, 
-	0x00, 0xD0, 0x01, 0x50, 0x02, 0x50, 0x03, 0x50, 0x04, 0x50, 0x05, 0x50, 0x06, 0x50, 0x07, 0x50, 0x08, 0x50, 
-	0x09, 0x50, 0x0A, 0x50, 0x0B, 0x50, 0x0C, 0x50, 0x0D, 0x50, 0x0E, 0x50, 0x0F, 0x50, 0x10, 0x50, 0x11, 0x50, 
-	0x12, 0x50, 0x13, 0x50, 0x14, 0x50, 0x15, 0x50, 0x16, 0x50, 0x17, 0x50, 0x18, 0x50, 0x19, 0x50, 0x1A, 0x50, 
-	0x1B, 0x50, 0x1C, 0x50, 0x1D, 0x50, 0x1E, 0x50, 0x1F, 0x50, 0x20, 0x50, 0x21, 0x50, 0x22, 0x50, 0x23, 0x50, 
-	0x24, 0x50, 0x25, 0x50, 0x26, 0x50, 0x27, 0x50, 0x28, 0x50, 0x29, 0x50, 0x2A, 0x50, 0x2B, 0x50, 0x2C, 0x50, 
-	0x2D, 0x50, 0x2E, 0x50, 0x2F, 0x50, 0x30, 0x50, 0x31, 0x50, 0x32, 0x50, 0x33, 0x50, 0x34, 0x50, 0x35, 0x50, 
-	0x36, 0x50, 0x37, 0x50, 0x38, 0x50, 0x39, 0x50, 0x3A, 0x50, 0x3B, 0x50, 0x3C, 0x50, 0x3D, 0x50, 0x3E, 0x50, 
-	0x3F, 0x50, 0x40, 0x50, 0x41, 0x50, 0x42, 0x50, 0x43, 0x50, 0x44, 0x50, 0x45, 0x50, 0x46, 0x50, 0x47, 0x50, 
-	0x48, 0x50, 0x49, 0x50, 0x4A, 0x50, 0x4B, 0x50, 0x4C, 0x50, 0x4D, 0x50, 0x4E, 0x50, 0x4F, 0x50, 0x50, 0x50, 
-	0x51, 0x50, 0x52, 0x50, 0x53, 0x50, 0x54, 0x50, 0x55, 0x50, 0x56, 0x50, 0x57, 0x50, 0x58, 0x50, 0x59, 0x50, 
-	0x5A, 0x50, 0x5B, 0x50, 0x5C, 0x50, 0x5D, 0x50, 0x5E, 0x50, 0x5F, 0x50, 0x60, 0x50, 0x61, 0x50, 0x62, 0x50, 
-	0x63, 0x50, 0x64, 0x50, 0x65, 0x50, 0x66, 0x50, 0x67, 0x50, 0x68, 0x50, 0x69, 0x50, 0x6A, 0x50, 0x6B, 0x50, 
-	0x6C, 0x50, 0x6D, 0x50, 0x6E, 0x50, 0x6F, 0x50, 0x70, 0x50, 0x71, 0x50, 0x72, 0x50, 0x73, 0x50, 0x74, 0x50, 
-	0x75, 0x50, 0x76, 0x50, 0x77, 0x50, 0x78, 0x50, 0x79, 0x50, 0x7A, 0x50, 0x7B, 0x50, 0x7C, 0x50, 0x7D, 0x50, 
-	0x7E, 0x50, 0x7F, 0x50, 0x80, 0x50, 0x81, 0x50, 0x82, 0x50, 0x83, 0x50, 0x84, 0x50, 0x85, 0x50, 0x86, 0x50, 
-	0x87, 0x50, 0x88, 0x50, 0x89, 0x50, 0x8A, 0x50, 0x8B, 0x50, 0x8C, 0x50, 0x8D, 0x50, 0x8E, 0x50, 0x8F, 0x50, 
-	0x90, 0x50, 0x91, 0x50, 0x92, 0x50, 0x93, 0x50, 0x94, 0x50, 0x95, 0x50, 0x96, 0x50, 0x97, 0x50, 0x98, 0x50, 
-	0x99, 0x50
-};
--- a/sys/src/games/gb/dat.h
+++ b/sys/src/games/gb/dat.h
@@ -1,81 +1,156 @@
-extern u16int pc, curpc, sp;
-extern u8int R[8], Fl;
-extern int halt, IME, keys;
-extern int clock, ppuclock, divclock, timerclock, timerfreq, timer;
-extern int rombank, rambank, ramen, battery, ramrom;
+typedef char s8int;
+typedef short s16int;
+typedef long s32int;
+typedef struct Event Event;
+typedef struct MBC3Timer MBC3Timer;
 
-extern uchar mem[], *ram;
+extern int trace;
+extern u16int curpc;
 
-extern uchar *cart;
-extern int mbc, rombanks, rambanks;
+extern uchar *rom, *back, reg[256], oam[256];
+extern MBC3Timer timer;
+extern uchar vram[16384];
+extern int nrom, nback, nbackbank;
+extern u32int pal[64];
+extern s8int dma;
+extern u32int divclock;
 
-extern int scale;
+extern Event *elist;
+extern ulong clock;
 
+extern u8int ppuy, ppustate;
+
+extern u8int mode;
+extern u8int mbc, feat;
+extern int keys;
+
 enum {
-	rB,
-	rC,
-	rD,
-	rE,
-	rH,
-	rL,
-	rHL,
-	rA
+	JOYP = 0x00,
+	SB = 0x01,
+	SC = 0x02,
+	DIV = 0x04,
+	TIMA = 0x05,
+	TMA = 0x06,
+	TAC = 0x07,
+	IF = 0x0F,
+	NR10 = 0x10,
+	NR11 = 0x11,
+	NR12 = 0x12,
+	NR13 = 0x13,
+	NR14 = 0x14,
+	NR21 = 0x16,
+	NR22 = 0x17,
+	NR23 = 0x18,
+	NR24 = 0x19,
+	NR30 = 0x1A,
+	NR31 = 0x1B,
+	NR32 = 0x1C,
+	NR33 = 0x1D,
+	NR34 = 0x1E,
+	NR41 = 0x20,
+	NR42 = 0x21,
+	NR43 = 0x22,
+	NR44 = 0x23,
+	NR50 = 0x24,
+	NR51 = 0x25,
+	NR52 = 0x26,
+	WAVE = 0x30,
+	LCDC = 0x40,
+	STAT = 0x41,
+	SCY = 0x42,
+	SCX = 0x43,
+	LY = 0x44,
+	LYC = 0x45,
+	DMA = 0x46,
+	BGP = 0x47,
+	OBP0 = 0x48,
+	OBP1 = 0x49,
+	WY = 0x4A,
+	WX = 0x4B,
+	KEY1 = 0x4D,
+	VBK = 0x4F,
+	HDMASL = 0x51,
+	HDMASH = 0x52,
+	HDMADL = 0x53,
+	HDMADH = 0x54,
+	HDMAC = 0x55,
+	
+	BCPS = 0x68,
+	BCPD = 0x69,
+	OCPS = 0x6A,
+	OCPD = 0x6B,
+	SVBK = 0x70,
+	IE = 0xFF
 };
 
 enum {
-	FLAGC = 0x10,
-	FLAGH = 0x20,
-	FLAGN = 0x40,
-	FLAGZ = 0x80,
+	LCDEN = 0x80,
+	WINMAP = 0x40,
+	WINEN = 0x20,
+	BGTILE = 0x10,
+	BGMAP = 0x08,
+	SPR16 = 0x04,
+	SPREN = 0x02,
+	BGEN = 0x01,
+	BGPRI = 0x01,
+	
+	IRQLYC = 0x40,
+	IRQM2 = 0x20,
+	IRQM1 = 0x10,
+	IRQM0 = 0x08,
+		
+	IRQVBL = 1,
+	IRQLCDS = 2,
+	IRQTIM = 4,
+	IRQSER = 8,
+	IRQJOY = 16,
 };
 
 enum {
-	/* interrupt types */
-	INTVBLANK  = 0,
-	INTLCDC    = 1,
-	INTTIMER   = 2,
-	INTSIO     = 3,
-	INTIRQ     = 4,
+	CGB = 1,
+	COL = 2,
+	TURBO = 4,
+	FORCEDMG = 8,
 
-	/* I/O registers */
-	DIV   = 0xFF04,
-	TIMA  = 0xFF05,
-	TMA   = 0xFF06,
-	TAC   = 0xFF07,
-	LY    = 0xFF44,
-	LCDC  = 0xFF40,
-	STAT  = 0xFF41,
-	SCY   = 0xFF42,
-	SCX   = 0xFF43,
-	LYC   = 0xFF45,
-	BGP   = 0xFF47,
-	OBP0  = 0xFF48,
-	OBP1  = 0xFF49,
-	WY    = 0xFF4A,
-	WX    = 0xFF4B,
-
-	/* LCDC */
-	BGDISP      = 1,
-	SPRITEDISP  = 2,
-	SPRITE16    = 4,
-	BGTILEMAP   = 8,
-	BGTILEDATA  = 16,
-	WINDOWDISP  = 32,
-	WINDOWTILEMAP  = 64,
-	LCDOP       = 128,
-
-	/* LCD STAT */
-	MODEHBLANK  = 0,
-	MODEVBLANK  = 1,
-	MODEOAM     = 2,
-	MODELCD     = 3,
+	FEATRAM = 1,
+	FEATBAT = 2,
+	FEATTIM = 4,
 	
-	/* others */
-	IF	= 0xFF0F,
-	IE	= 0xFFFF,
-	CPUFREQ = 4194304,
-	
+	INIT = -1,
+	SAVE = -2,
+	RSTR = -3,
+	READ = -4,
+};
+
+enum {
+	TIMERSIZ = 18,
+	PICW = 160,
+	PICH = 144,
 	MILLION = 1000000,
 	BILLION = 1000000000,
-	SAMPLE = 44100,
 };
+
+struct Event {
+	int time;
+	void (*f)(void *);
+	Event *next;
+	void *aux;
+};
+extern Event *elist;
+
+struct MBC3Timer {
+	vlong ns;
+	u8int sec, min, hr, dl, dh;
+};
+
+typedef struct Var Var;
+
+struct Var {
+	void *a;
+	int s, n;
+};
+#define VAR(a) {&a, sizeof(a), 1}
+#define ARR(a) {a, sizeof(*a), nelem(a)}
+enum { NEVENT = 5 };
+extern int (*mapper)(int, int);
+extern u32int moncols[4];
--- a/sys/src/games/gb/disasm.c
+++ /dev/null
@@ -1,811 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include "dat.h"
-#include "fns.h"
-
-static char *opcodes[256] = {
-	[0x00] "NOP",
-	[0x01] "LD BC,%.4x",
-	[0x02] "LD (BC),A",
-	[0x03] "INC BC",
-	[0x04] "INC B",
-	[0x05] "DEC B",
-	[0x06] "LD B,%.2x",
-	[0x07] "RLCA ",
-	[0x08] "LD (%.4x),SP",
-	[0x09] "ADD HL,BC",
-	[0x0A] "LD A,(BC)",
-	[0x0B] "DEC BC",
-	[0x0C] "INC C",
-	[0x0D] "DEC C",
-	[0x0E] "LD C,%.2x",
-	[0x0F] "RRCA ",
-	[0x10] "STOP",
-	[0x11] "LD DE,%.4x",
-	[0x12] "LD (DE),A",
-	[0x13] "INC DE",
-	[0x14] "INC D",
-	[0x15] "DEC D",
-	[0x16] "LD D,%.2x",
-	[0x17] "RLA ",
-	[0x18] "JR %.2x",
-	[0x19] "ADD HL,DE",
-	[0x1A] "LD A,(DE)",
-	[0x1B] "DEC DE",
-	[0x1C] "INC E",
-	[0x1D] "DEC E",
-	[0x1E] "LD E,%.2x",
-	[0x1F] "RRA ",
-	[0x20] "JR NZ,%.2x",
-	[0x21] "LD HL,%.4x",
-	[0x22] "LD (HLI),A",
-	[0x23] "INC HL",
-	[0x24] "INC H",
-	[0x25] "DEC H",
-	[0x26] "LD H,%.2x",
-	[0x27] "DAA ",
-	[0x28] "JR Z,%.2x",
-	[0x29] "ADD HL,HL",
-	[0x2A] "LD A,(HLI)",
-	[0x2B] "DEC HL",
-	[0x2C] "INC L",
-	[0x2D] "DEC L",
-	[0x2E] "LD L,%.2x",
-	[0x2F] "CPL ",
-	[0x30] "JR NC,%.2x",
-	[0x31] "LD SP,%.4x",
-	[0x32] "LD (HLD),A",
-	[0x33] "INC SP",
-	[0x34] "INC (HL)",
-	[0x35] "DEC (HL)",
-	[0x36] "LD (HL),%.2x",
-	[0x37] "SCF ",
-	[0x38] "JR C,%.2x",
-	[0x39] "ADD HL,SP",
-	[0x3A] "LD A,(HLD)",
-	[0x3B] "DEC SP",
-	[0x3C] "INC A",
-	[0x3D] "DEC A",
-	[0x3E] "LD A,%.2x",
-	[0x3F] "CCF ",
-	[0x40] "LD B,B",
-	[0x41] "LD B,C",
-	[0x42] "LD B,D",
-	[0x43] "LD B,E",
-	[0x44] "LD B,H",
-	[0x45] "LD B,L",
-	[0x46] "LD B,(HL)",
-	[0x47] "LD B,A",
-	[0x48] "LD C,B",
-	[0x49] "LD C,C",
-	[0x4A] "LD C,D",
-	[0x4B] "LD C,E",
-	[0x4C] "LD C,H",
-	[0x4D] "LD C,L",
-	[0x4E] "LD C,(HL)",
-	[0x4F] "LD C,A",
-	[0x50] "LD D,B",
-	[0x51] "LD D,C",
-	[0x52] "LD D,D",
-	[0x53] "LD D,E",
-	[0x54] "LD D,H",
-	[0x55] "LD D,L",
-	[0x56] "LD D,(HL)",
-	[0x57] "LD D,A",
-	[0x58] "LD E,B",
-	[0x59] "LD E,C",
-	[0x5A] "LD E,D",
-	[0x5B] "LD E,E",
-	[0x5C] "LD E,H",
-	[0x5D] "LD E,L",
-	[0x5E] "LD E,(HL)",
-	[0x5F] "LD E,A",
-	[0x60] "LD H,B",
-	[0x61] "LD H,C",
-	[0x62] "LD H,D",
-	[0x63] "LD H,E",
-	[0x64] "LD H,H",
-	[0x65] "LD H,L",
-	[0x66] "LD H,(HL)",
-	[0x67] "LD H,A",
-	[0x68] "LD L,B",
-	[0x69] "LD L,C",
-	[0x6A] "LD L,D",
-	[0x6B] "LD L,E",
-	[0x6C] "LD L,H",
-	[0x6D] "LD L,L",
-	[0x6E] "LD L,(HL)",
-	[0x6F] "LD L,A",
-	[0x70] "LD (HL),B",
-	[0x71] "LD (HL),C",
-	[0x72] "LD (HL),D",
-	[0x73] "LD (HL),E",
-	[0x74] "LD (HL),H",
-	[0x75] "LD (HL),L",
-	[0x76] "HALT ",
-	[0x77] "LD (HL),A",
-	[0x78] "LD A,B",
-	[0x79] "LD A,C",
-	[0x7A] "LD A,D",
-	[0x7B] "LD A,E",
-	[0x7C] "LD A,H",
-	[0x7D] "LD A,L",
-	[0x7E] "LD A,(HL)",
-	[0x7F] "LD A,A",
-	[0x80] "ADD A,B",
-	[0x81] "ADD A,C",
-	[0x82] "ADD A,D",
-	[0x83] "ADD A,E",
-	[0x84] "ADD A,H",
-	[0x85] "ADD A,L",
-	[0x86] "ADD A,(HL)",
-	[0x87] "ADD A,A",
-	[0x88] "ADC A,B",
-	[0x89] "ADC A,C",
-	[0x8A] "ADC A,D",
-	[0x8B] "ADC A,E",
-	[0x8C] "ADC A,H",
-	[0x8D] "ADC A,L",
-	[0x8E] "ADC A,(HL)",
-	[0x8F] "ADC A,A",
-	[0x90] "SUB B",
-	[0x91] "SUB C",
-	[0x92] "SUB D",
-	[0x93] "SUB E",
-	[0x94] "SUB H",
-	[0x95] "SUB L",
-	[0x96] "SUB (HL)",
-	[0x97] "SUB A",
-	[0x98] "SBC B",
-	[0x99] "SBC C",
-	[0x9A] "SBC D",
-	[0x9B] "SBC E",
-	[0x9C] "SBC H",
-	[0x9D] "SBC L",
-	[0x9E] "SBC (HL)",
-	[0x9F] "SBC A",
-	[0xA0] "AND B",
-	[0xA1] "AND C",
-	[0xA2] "AND D",
-	[0xA3] "AND E",
-	[0xA4] "AND H",
-	[0xA5] "AND L",
-	[0xA6] "AND (HL)",
-	[0xA7] "AND A",
-	[0xA8] "XOR B",
-	[0xA9] "XOR C",
-	[0xAA] "XOR D",
-	[0xAB] "XOR E",
-	[0xAC] "XOR H",
-	[0xAD] "XOR L",
-	[0xAE] "XOR (HL)",
-	[0xAF] "XOR A",
-	[0xB0] "OR B",
-	[0xB1] "OR C",
-	[0xB2] "OR D",
-	[0xB3] "OR E",
-	[0xB4] "OR H",
-	[0xB5] "OR L",
-	[0xB6] "OR (HL)",
-	[0xB7] "OR A",
-	[0xB8] "CP B",
-	[0xB9] "CP C",
-	[0xBA] "CP D",
-	[0xBB] "CP E",
-	[0xBC] "CP H",
-	[0xBD] "CP L",
-	[0xBE] "CP (HL)",
-	[0xBF] "CP A",
-	[0xC0] "RET NZ",
-	[0xC1] "POP BC",
-	[0xC2] "JP NZ,%.4x",
-	[0xC3] "JP %.4x",
-	[0xC4] "CALL NZ,%.4x",
-	[0xC5] "PUSH BC",
-	[0xC6] "ADD A,%.2x",
-	[0xC7] "RST 00H",
-	[0xC8] "RET Z",
-	[0xC9] "RET ",
-	[0xCA] "JP Z,%.4x",
-	[0xCB] "#CB ",
-	[0xCC] "CALL Z,%.4x",
-	[0xCD] "CALL %.4x",
-	[0xCE] "ADC A,%.2x",
-	[0xCF] "RST 08H",
-	[0xD0] "RET NC",
-	[0xD1] "POP DE",
-	[0xD2] "JP NC,%.4x",
-	[0xD3] "---",
-	[0xD4] "CALL NC,%.4x",
-	[0xD5] "PUSH DE",
-	[0xD6] "SUB %.2x",
-	[0xD7] "RST 10H",
-	[0xD8] "RET C",
-	[0xD9] "RETI",
-	[0xDA] "JP C,%.4x",
-	[0xDB] "---",
-	[0xDC] "CALL C,%.4x",
-	[0xDD] "---",
-	[0xDE] "SBC A,%.2x",
-	[0xDF] "RST 18H",
-	[0xE0] "LD (ff%.2x),A",
-	[0xE1] "POP HL",
-	[0xE2] "LD (C),A",
-	[0xE3] "---",
-	[0xE4] "---",
-	[0xE5] "PUSH HL",
-	[0xE6] "AND %.2x",
-	[0xE7] "RST 20H",
-	[0xE8] "ADD SP,%.2x",
-	[0xE9] "JP (HL)",
-	[0xEA] "LD (%.4x),A",
-	[0xEB] "---",
-	[0xEC] "---",
-	[0xED] "#ED ",
-	[0xEE] "XOR %.2x",
-	[0xEF] "RST 28H",
-	[0xF0] "LD A,(ff%.2x)",
-	[0xF1] "POP AF",
-	[0xF2] "LD A, (C)",
-	[0xF3] "DI ",
-	[0xF4] "---",
-	[0xF5] "PUSH AF",
-	[0xF6] "OR %.2x",
-	[0xF7] "RST 30H",
-	[0xF8] "LDHL SP,%.2x",
-	[0xF9] "LD SP,HL",
-	[0xFA] "LD A,(%.4x)",
-	[0xFB] "EI ",
-	[0xFC] "---",
-	[0xFD] "---",
-	[0xFE] "CP %.2x",
-	[0xFF] "RST 38H",
-};
-
-static int operands[256] = {
-	[0x00] 0,
-	[0x01] 2,
-	[0x02] 0,
-	[0x03] 0,
-	[0x04] 0,
-	[0x05] 0,
-	[0x06] 1,
-	[0x07] 0,
-	[0x08] 0,
-	[0x09] 0,
-	[0x0A] 0,
-	[0x0B] 0,
-	[0x0C] 0,
-	[0x0D] 0,
-	[0x0E] 1,
-	[0x0F] 0,
-	[0x10] 0,
-	[0x11] 2,
-	[0x12] 0,
-	[0x13] 0,
-	[0x14] 0,
-	[0x15] 0,
-	[0x16] 1,
-	[0x17] 0,
-	[0x18] 1,
-	[0x19] 0,
-	[0x1A] 0,
-	[0x1B] 0,
-	[0x1C] 0,
-	[0x1D] 0,
-	[0x1E] 1,
-	[0x1F] 0,
-	[0x20] 1,
-	[0x21] 2,
-	[0x22] 0,
-	[0x23] 0,
-	[0x24] 0,
-	[0x25] 0,
-	[0x26] 1,
-	[0x27] 0,
-	[0x28] 1,
-	[0x29] 0,
-	[0x2A] 0,
-	[0x2B] 0,
-	[0x2C] 0,
-	[0x2D] 0,
-	[0x2E] 1,
-	[0x2F] 0,
-	[0x30] 1,
-	[0x31] 2,
-	[0x32] 0,
-	[0x33] 0,
-	[0x34] 0,
-	[0x35] 0,
-	[0x36] 1,
-	[0x37] 0,
-	[0x38] 1,
-	[0x39] 0,
-	[0x3A] 2,
-	[0x3B] 0,
-	[0x3C] 0,
-	[0x3D] 0,
-	[0x3E] 1,
-	[0x3F] 0,
-	[0x40] 0,
-	[0x41] 0,
-	[0x42] 0,
-	[0x43] 0,
-	[0x44] 0,
-	[0x45] 0,
-	[0x46] 0,
-	[0x47] 0,
-	[0x48] 0,
-	[0x49] 0,
-	[0x4A] 0,
-	[0x4B] 0,
-	[0x4C] 0,
-	[0x4D] 0,
-	[0x4E] 0,
-	[0x4F] 0,
-	[0x50] 0,
-	[0x51] 0,
-	[0x52] 0,
-	[0x53] 0,
-	[0x54] 0,
-	[0x55] 0,
-	[0x56] 0,
-	[0x57] 0,
-	[0x58] 0,
-	[0x59] 0,
-	[0x5A] 0,
-	[0x5B] 0,
-	[0x5C] 0,
-	[0x5D] 0,
-	[0x5E] 0,
-	[0x5F] 0,
-	[0x60] 0,
-	[0x61] 0,
-	[0x62] 0,
-	[0x63] 0,
-	[0x64] 0,
-	[0x65] 0,
-	[0x66] 0,
-	[0x67] 0,
-	[0x68] 0,
-	[0x69] 0,
-	[0x6A] 0,
-	[0x6B] 0,
-	[0x6C] 0,
-	[0x6D] 0,
-	[0x6E] 0,
-	[0x6F] 0,
-	[0x70] 0,
-	[0x71] 0,
-	[0x72] 0,
-	[0x73] 0,
-	[0x74] 0,
-	[0x75] 0,
-	[0x76] 0,
-	[0x77] 0,
-	[0x78] 0,
-	[0x79] 0,
-	[0x7A] 0,
-	[0x7B] 0,
-	[0x7C] 0,
-	[0x7D] 0,
-	[0x7E] 0,
-	[0x7F] 0,
-	[0x80] 0,
-	[0x81] 0,
-	[0x82] 0,
-	[0x83] 0,
-	[0x84] 0,
-	[0x85] 0,
-	[0x86] 0,
-	[0x87] 0,
-	[0x88] 0,
-	[0x89] 0,
-	[0x8A] 0,
-	[0x8B] 0,
-	[0x8C] 0,
-	[0x8D] 0,
-	[0x8E] 0,
-	[0x8F] 0,
-	[0x90] 0,
-	[0x91] 0,
-	[0x92] 0,
-	[0x93] 0,
-	[0x94] 0,
-	[0x95] 0,
-	[0x96] 0,
-	[0x97] 0,
-	[0x98] 0,
-	[0x99] 0,
-	[0x9A] 0,
-	[0x9B] 0,
-	[0x9C] 0,
-	[0x9D] 0,
-	[0x9E] 0,
-	[0x9F] 0,
-	[0xA0] 0,
-	[0xA1] 0,
-	[0xA2] 0,
-	[0xA3] 0,
-	[0xA4] 0,
-	[0xA5] 0,
-	[0xA6] 0,
-	[0xA7] 0,
-	[0xA8] 0,
-	[0xA9] 0,
-	[0xAA] 0,
-	[0xAB] 0,
-	[0xAC] 0,
-	[0xAD] 0,
-	[0xAE] 0,
-	[0xAF] 0,
-	[0xB0] 0,
-	[0xB1] 0,
-	[0xB2] 0,
-	[0xB3] 0,
-	[0xB4] 0,
-	[0xB5] 0,
-	[0xB6] 0,
-	[0xB7] 0,
-	[0xB8] 0,
-	[0xB9] 0,
-	[0xBA] 0,
-	[0xBB] 0,
-	[0xBC] 0,
-	[0xBD] 0,
-	[0xBE] 0,
-	[0xBF] 0,
-	[0xC0] 0,
-	[0xC1] 0,
-	[0xC2] 2,
-	[0xC3] 2,
-	[0xC4] 2,
-	[0xC5] 0,
-	[0xC6] 1,
-	[0xC7] 0,
-	[0xC8] 0,
-	[0xC9] 0,
-	[0xCA] 2,
-	[0xCB] 0,
-	[0xCC] 2,
-	[0xCD] 2,
-	[0xCE] 1,
-	[0xCF] 0,
-	[0xD0] 0,
-	[0xD1] 0,
-	[0xD2] 2,
-	[0xD3] 1,
-	[0xD4] 2,
-	[0xD5] 0,
-	[0xD6] 1,
-	[0xD7] 0,
-	[0xD8] 0,
-	[0xD9] 0,
-	[0xDA] 2,
-	[0xDB] 1,
-	[0xDC] 2,
-	[0xDD] 0,
-	[0xDE] 1,
-	[0xDF] 0,
-	[0xE0] 1,
-	[0xE1] 0,
-	[0xE2] 0,
-	[0xE3] 0,
-	[0xE4] 2,
-	[0xE5] 0,
-	[0xE6] 1,
-	[0xE7] 0,
-	[0xE8] 1,
-	[0xE9] 0,
-	[0xEA] 2,
-	[0xEB] 0,
-	[0xEC] 2,
-	[0xED] 0,
-	[0xEE] 1,
-	[0xEF] 0,
-	[0xF0] 1,
-	[0xF1] 0,
-	[0xF2] 0,
-	[0xF3] 0,
-	[0xF4] 2,
-	[0xF5] 0,
-	[0xF6] 1,
-	[0xF7] 0,
-	[0xF8] 1,
-	[0xF9] 0,
-	[0xFA] 2,
-	[0xFB] 0,
-	[0xFC] 2,
-	[0xFD] 0,
-	[0xFE] 1,
-	[0xFF] 0,
-};
-
-static char *cbopcodes[256] = {
-	[0x00] "RLC B",
-	[0x01] "RLC C",
-	[0x02] "RLC D",
-	[0x03] "RLC E",
-	[0x04] "RLC H",
-	[0x05] "RLC L",
-	[0x06] "RLC (HL)",
-	[0x07] "RLC A",
-	[0x08] "RRC B",
-	[0x09] "RRC C",
-	[0x0A] "RRC D",
-	[0x0B] "RRC E",
-	[0x0C] "RRC H",
-	[0x0D] "RRC L",
-	[0x0E] "RRC (HL)",
-	[0x0F] "RRC A",
-	[0x10] "RL B",
-	[0x11] "RL C",
-	[0x12] "RL D",
-	[0x13] "RL E",
-	[0x14] "RL H",
-	[0x15] "RL L",
-	[0x16] "RL (HL)",
-	[0x17] "RL A",
-	[0x18] "RR B",
-	[0x19] "RR C",
-	[0x1A] "RR D",
-	[0x1B] "RR E",
-	[0x1C] "RR H",
-	[0x1D] "RR L",
-	[0x1E] "RR (HL)",
-	[0x1F] "RR A",
-	[0x20] "SLA B",
-	[0x21] "SLA C",
-	[0x22] "SLA D",
-	[0x23] "SLA E",
-	[0x24] "SLA H",
-	[0x25] "SLA L",
-	[0x26] "SLA (HL)",
-	[0x27] "SLA A",
-	[0x28] "SRA B",
-	[0x29] "SRA C",
-	[0x2A] "SRA D",
-	[0x2B] "SRA E",
-	[0x2C] "SRA H",
-	[0x2D] "SRA L",
-	[0x2E] "SRA (HL)",
-	[0x2F] "SRA A",
-	[0x30] "SWAP B",
-	[0x31] "SWAP C",
-	[0x32] "SWAP D",
-	[0x33] "SWAP E",
-	[0x34] "SWAP H",
-	[0x35] "SWAP L",
-	[0x36] "SWAP (HL)",
-	[0x37] "SWAP A",
-	[0x38] "SRL B",
-	[0x39] "SRL C",
-	[0x3A] "SRL D",
-	[0x3B] "SRL E",
-	[0x3C] "SRL H",
-	[0x3D] "SRL L",
-	[0x3E] "SRL (HL)",
-	[0x3F] "SRL A",
-	[0x40] "BIT 0,B",
-	[0x41] "BIT 0,C",
-	[0x42] "BIT 0,D",
-	[0x43] "BIT 0,E",
-	[0x44] "BIT 0,H",
-	[0x45] "BIT 0,L",
-	[0x46] "BIT 0,(HL)",
-	[0x47] "BIT 0,A",
-	[0x48] "BIT 1,B",
-	[0x49] "BIT 1,C",
-	[0x4A] "BIT 1,D",
-	[0x4B] "BIT 1,E",
-	[0x4C] "BIT 1,H",
-	[0x4D] "BIT 1,L",
-	[0x4E] "BIT 1,(HL)",
-	[0x4F] "BIT 1,A",
-	[0x50] "BIT 2,B",
-	[0x51] "BIT 2,C",
-	[0x52] "BIT 2,D",
-	[0x53] "BIT 2,E",
-	[0x54] "BIT 2,H",
-	[0x55] "BIT 2,L",
-	[0x56] "BIT 2,(HL)",
-	[0x57] "BIT 2,A",
-	[0x58] "BIT 3,B",
-	[0x59] "BIT 3,C",
-	[0x5A] "BIT 3,D",
-	[0x5B] "BIT 3,E",
-	[0x5C] "BIT 3,H",
-	[0x5D] "BIT 3,L",
-	[0x5E] "BIT 3,(HL)",
-	[0x5F] "BIT 3,A",
-	[0x60] "BIT 4,B",
-	[0x61] "BIT 4,C",
-	[0x62] "BIT 4,D",
-	[0x63] "BIT 4,E",
-	[0x64] "BIT 4,H",
-	[0x65] "BIT 4,L",
-	[0x66] "BIT 4,(HL)",
-	[0x67] "BIT 4,A",
-	[0x68] "BIT 5,B",
-	[0x69] "BIT 5,C",
-	[0x6A] "BIT 5,D",
-	[0x6B] "BIT 5,E",
-	[0x6C] "BIT 5,H",
-	[0x6D] "BIT 5,L",
-	[0x6E] "BIT 5,(HL)",
-	[0x6F] "BIT 5,A",
-	[0x70] "BIT 6,B",
-	[0x71] "BIT 6,C",
-	[0x72] "BIT 6,D",
-	[0x73] "BIT 6,E",
-	[0x74] "BIT 6,H",
-	[0x75] "BIT 6,L",
-	[0x76] "BIT 6,(HL)",
-	[0x77] "BIT 6,A",
-	[0x78] "BIT 7,B",
-	[0x79] "BIT 7,C",
-	[0x7A] "BIT 7,D",
-	[0x7B] "BIT 7,E",
-	[0x7C] "BIT 7,H",
-	[0x7D] "BIT 7,L",
-	[0x7E] "BIT 7,(HL)",
-	[0x7F] "BIT 7,A",
-	[0x80] "RES 0,B",
-	[0x81] "RES 0,C",
-	[0x82] "RES 0,D",
-	[0x83] "RES 0,E",
-	[0x84] "RES 0,H",
-	[0x85] "RES 0,L",
-	[0x86] "RES 0,(HL)",
-	[0x87] "RES 0,A",
-	[0x88] "RES 1,B",
-	[0x89] "RES 1,C",
-	[0x8A] "RES 1,D",
-	[0x8B] "RES 1,E",
-	[0x8C] "RES 1,H",
-	[0x8D] "RES 1,L",
-	[0x8E] "RES 1,(HL)",
-	[0x8F] "RES 1,A",
-	[0x90] "RES 2,B",
-	[0x91] "RES 2,C",
-	[0x92] "RES 2,D",
-	[0x93] "RES 2,E",
-	[0x94] "RES 2,H",
-	[0x95] "RES 2,L",
-	[0x96] "RES 2,(HL)",
-	[0x97] "RES 2,A",
-	[0x98] "RES 3,B",
-	[0x99] "RES 3,C",
-	[0x9A] "RES 3,D",
-	[0x9B] "RES 3,E",
-	[0x9C] "RES 3,H",
-	[0x9D] "RES 3,L",
-	[0x9E] "RES 3,(HL)",
-	[0x9F] "RES 3,A",
-	[0xA0] "RES 4,B",
-	[0xA1] "RES 4,C",
-	[0xA2] "RES 4,D",
-	[0xA3] "RES 4,E",
-	[0xA4] "RES 4,H",
-	[0xA5] "RES 4,L",
-	[0xA6] "RES 4,(HL)",
-	[0xA7] "RES 4,A",
-	[0xA8] "RES 5,B",
-	[0xA9] "RES 5,C",
-	[0xAA] "RES 5,D",
-	[0xAB] "RES 5,E",
-	[0xAC] "RES 5,H",
-	[0xAD] "RES 5,L",
-	[0xAE] "RES 5,(HL)",
-	[0xAF] "RES 5,A",
-	[0xB0] "RES 6,B",
-	[0xB1] "RES 6,C",
-	[0xB2] "RES 6,D",
-	[0xB3] "RES 6,E",
-	[0xB4] "RES 6,H",
-	[0xB5] "RES 6,L",
-	[0xB6] "RES 6,(HL)",
-	[0xB7] "RES 6,A",
-	[0xB8] "RES 7,B",
-	[0xB9] "RES 7,C",
-	[0xBA] "RES 7,D",
-	[0xBB] "RES 7,E",
-	[0xBC] "RES 7,H",
-	[0xBD] "RES 7,L",
-	[0xBE] "RES 7,(HL)",
-	[0xBF] "RES 7,A",
-	[0xC0] "SET 0,B",
-	[0xC1] "SET 0,C",
-	[0xC2] "SET 0,D",
-	[0xC3] "SET 0,E",
-	[0xC4] "SET 0,H",
-	[0xC5] "SET 0,L",
-	[0xC6] "SET 0,(HL)",
-	[0xC7] "SET 0,A",
-	[0xC8] "SET 1,B",
-	[0xC9] "SET 1,C",
-	[0xCA] "SET 1,D",
-	[0xCB] "SET 1,E",
-	[0xCC] "SET 1,H",
-	[0xCD] "SET 1,L",
-	[0xCE] "SET 1,(HL)",
-	[0xCF] "SET 1,A",
-	[0xD0] "SET 2,B",
-	[0xD1] "SET 2,C",
-	[0xD2] "SET 2,D",
-	[0xD3] "SET 2,E",
-	[0xD4] "SET 2,H",
-	[0xD5] "SET 2,L",
-	[0xD6] "SET 2,(HL)",
-	[0xD7] "SET 2,A",
-	[0xD8] "SET 3,B",
-	[0xD9] "SET 3,C",
-	[0xDA] "SET 3,D",
-	[0xDB] "SET 3,E",
-	[0xDC] "SET 3,H",
-	[0xDD] "SET 3,L",
-	[0xDE] "SET 3,(HL)",
-	[0xDF] "SET 3,A",
-	[0xE0] "SET 4,B",
-	[0xE1] "SET 4,C",
-	[0xE2] "SET 4,D",
-	[0xE3] "SET 4,E",
-	[0xE4] "SET 4,H",
-	[0xE5] "SET 4,L",
-	[0xE6] "SET 4,(HL)",
-	[0xE7] "SET 4,A",
-	[0xE8] "SET 5,B",
-	[0xE9] "SET 5,C",
-	[0xEA] "SET 5,D",
-	[0xEB] "SET 5,E",
-	[0xEC] "SET 5,H",
-	[0xED] "SET 5,L",
-	[0xEE] "SET 5,(HL)",
-	[0xEF] "SET 5,A",
-	[0xF0] "SET 6,B",
-	[0xF1] "SET 6,C",
-	[0xF2] "SET 6,D",
-	[0xF3] "SET 6,E",
-	[0xF4] "SET 6,H",
-	[0xF5] "SET 6,L",
-	[0xF6] "SET 6,(HL)",
-	[0xF7] "SET 6,A",
-	[0xF8] "SET 7,B",
-	[0xF9] "SET 7,C",
-	[0xFA] "SET 7,D",
-	[0xFB] "SET 7,E",
-	[0xFC] "SET 7,H",
-	[0xFD] "SET 7,L",
-	[0xFE] "SET 7,(HL)",
-	[0xFF] "SET 7,A",
-};
-
-void
-disasm(u16int addr)
-{
-	u8int op;
-	int x;
-
-	op = memread(addr);
-	if(op == 0xCB){
-		op = memread(addr + 1);
-		print("%s\n", cbopcodes[op]);
-		return;
-	}
-	switch(operands[op]){
-	case 0:
-		print(opcodes[op]);
-		break;
-	case 1:
-		print(opcodes[op], (int)(memread(addr + 1)));
-		break;
-	case 2:
-		x = (uint)memread(addr + 2);
-		x <<= 8;
-		x |= (uint)memread(addr + 1);
-		print(opcodes[op], x);
-	}
-	print("\n");
-}
--- /dev/null
+++ b/sys/src/games/gb/ev.c
@@ -1,0 +1,122 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+Event evhblank, evtimer, evnever;
+extern Event evsamp, evenv;
+Event *events[NEVENT] = {&evhblank, &evtimer, &evnever, &evsamp, &evenv};
+Event *elist;
+static int timshtab[4] = {12, 4, 6, 8}, timsh;
+ulong timclock;
+Var evvars[] = {VAR(timsh), VAR(timclock), {nil, 0, 0}};
+
+void
+addevent(Event *ev, int time)
+{
+	Event **p, *e;
+	int t;
+	
+	assert(time >= 0);
+	t = time;
+	for(p = &elist; (e = *p) != nil; p = &e->next){
+		if(t < e->time){
+			e->time -= t;
+			break;
+		}
+		t -= e->time;
+	}
+	ev->next = e;
+	ev->time = t;
+	*p = ev;
+}
+
+void
+delevent(Event *ev)
+{
+	Event **p, *e;
+	
+	for(p = &elist; (e = *p) != nil; p = &e->next)
+		if(e == ev){
+			*p = e->next;
+			if(e->next != nil)
+				e->next->time += e->time;
+			return;
+		}
+}
+
+void
+popevent(void)
+{
+	Event *e;
+	int t;
+	
+	do{
+		e = elist;
+		t = e->time;
+		elist = e->next;
+		e->f(e->aux);
+	}while((elist->time += t) <= 0);
+}
+
+void
+timerset(void)
+{
+	timclock = clock & -(1<<timsh);
+	if((reg[TAC] & 4) != 0){
+		delevent(&evtimer);
+		addevent(&evtimer, 0x100 - reg[TIMA] << timsh);// | -clock & (1<<timsh)-1);
+	}
+}
+
+void
+timertac(u8int n, int t)
+{
+	if((reg[TAC] & 7) == (n & 7) && !t)
+		return;
+	if((reg[TAC] & 4) != 0){
+		delevent(&evtimer);
+		reg[TIMA] += clock - timclock >> timsh;
+	}
+	timclock = clock & -(1<<timsh);
+	timsh = timshtab[n & 3];
+	if((mode & TURBO) == 0)
+		 timsh++;
+	if((n & 4) != 0)
+		addevent(&evtimer, 0x100 - reg[TIMA] << timsh | -clock & (1<<timsh)-1);
+}
+
+u8int
+timread(void)
+{
+	if((reg[TAC] & 4) == 0)
+		return reg[TIMA];
+	return reg[TIMA] + (clock - timclock >> timsh);
+}
+
+void
+timertick(void *)
+{
+	reg[TIMA] = reg[TMA];
+	addevent(&evtimer, 0x100 - reg[TIMA] << timsh);
+	reg[IF] |= IRQTIM;
+}
+
+void
+nevertick(void *)
+{
+	addevent(&evnever, 10000000);
+}
+
+void
+eventinit(void)
+{
+	extern void hblanktick(void *);
+	
+	evhblank.f = hblanktick;
+	addevent(&evhblank, 240*4);
+	evtimer.f = timertick;
+	evnever.f = nevertick;
+	addevent(&evnever, 10000000);
+}
--- a/sys/src/games/gb/fns.h
+++ b/sys/src/games/gb/fns.h
@@ -1,14 +1,29 @@
 u8int memread(u16int);
 void memwrite(u16int, u8int);
+void addevent(Event *, int);
+void delevent(Event *);
+void popevent(void);
+void eventinit(void);
+void meminit(void);
+void reset(void);
 int step(void);
-void ppustep(void);
-void disasm(u16int);
-void interrupt(u8int);
-void message(char *, ...);
-void flushram(void);
-void savestate(char *);
+void ppusync(void);
+void ppuinit(void);
+void flush(void);
+void timertac(u8int, int);
+void timerset(void);
+void writeback(void);
 void loadstate(char *);
-void initaudio(void);
-void audiosample(void);
+void savestate(char *);
+void flushback(void);
+void getvars(Var *);
+void putvars(Var *);
+void memload(void);
+int dmastep(void);
+void audioinit(void);
 int audioout(void);
-void flush(void);
+void sndwrite(u8int, u8int);
+int apuread(void);
+u8int waveread(u8int);
+void wavewrite(u8int, u8int);
+u8int timread(void);
--- a/sys/src/games/gb/gb.c
+++ b/sys/src/games/gb/gb.c
@@ -1,196 +1,262 @@
 #include <u.h>
 #include <libc.h>
-#include <draw.h>
 #include <thread.h>
+#include <draw.h>
 #include <mouse.h>
-#include <cursor.h>
 #include <keyboard.h>
 #include "dat.h"
 #include "fns.h"
 
-uchar *cart, *ram;
-int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, audioclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale, paused;
+int cpuhalt;
+int scale, profile;
 Rectangle picr;
 Image *bg, *tmp;
 Mousectl *mc;
+int keys, paused, framestep, backup;
 QLock pauselock;
+int savefd = -1, saveframes;
+ulong clock;
+int savereq, loadreq;
+u8int mbc, feat, mode;
+extern MBC3Timer timer, timerl;
 
-void
-message(char *fmt, ...)
+void *
+emalloc(ulong sz)
 {
-	va_list va;
-	char buf[512];
+	void *v;
 	
-	va_start(va, fmt);
-	vsnprint(buf, sizeof buf, fmt, va);
-	string(screen, Pt(10, 10), display->black, ZP, display->defaultfont, buf);
-	msgclock = CPUFREQ;
-	va_end(va);
+	v = malloc(sz);
+	if(v == nil)
+		sysfatal("malloc: %r");
+	setmalloctag(v, getcallerpc(&sz));
+	return v;
 }
 
 void
-loadrom(char *file)
+writeback(void)
 {
-	int fd, i;
-	vlong len;
-	u8int ck;
-	char buf[512];
-	char title[17];
-	Point p;
-	char *s;
-	extern int battery, ramen;
+	if(saveframes == 0)
+		saveframes = 15;
+}
+
+void
+timerload(char *buf)
+{
+	timer.ns = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24 | (uvlong)buf[4] << 32 | (uvlong)buf[5] << 40 | (uvlong)buf[6] << 48LL | (uvlong)buf[7] << 56LL;
+	timer.sec = buf[8];
+	timer.min = buf[9];
+	timer.hr = buf[10];
+	timer.dl = buf[11];
+	timer.dh = buf[12];
+	timerl.sec = buf[13];
+	timerl.min = buf[14];
+	timerl.hr = buf[15];
+	timerl.dl = buf[16];
+	timerl.dh = buf[17];
+}
+
+void
+timersave(char *buf)
+{
+	buf[0] = timer.ns;
+	buf[1] = timer.ns >> 8;
+	buf[2] = timer.ns >> 16;
+	buf[3] = timer.ns >> 24;
+	buf[4] = timer.ns >> 32;
+	buf[5] = timer.ns >> 40;
+	buf[6] = timer.ns >> 48;
+	buf[7] = timer.ns >> 56;
+	buf[8] = timer.sec;
+	buf[9] = timer.min;
+	buf[10] = timer.hr;
+	buf[11] = timer.dl;
+	buf[12] = timer.dh;
+	buf[13] = timerl.sec;
+	buf[14] = timerl.min;
+	buf[15] = timerl.hr;
+	buf[16] = timerl.dl;
+	buf[17] = timerl.dh;
+}
+
+void
+flushback(void)
+{
+	char buf[TIMERSIZ];
+
+	if(savefd >= 0){
+		pwrite(savefd, back, nback, 0);
+		timersave(buf);
+		pwrite(savefd, buf, TIMERSIZ, nback);
+	}
+	saveframes = 0;
+}
+
+void
+loadsave(char *file)
+{
+	char *buf, *p;
+	char tim[TIMERSIZ];
+
+	buf = emalloc(strlen(file) + 4);
+	strcpy(buf, file);
+	p = strchr(buf, '.');
+	if(p == nil)
+		p = buf + strlen(buf);
+	strcpy(p, ".sav");
+	savefd = open(buf, ORDWR);
+	if(savefd < 0){
+		savefd = create(buf, OWRITE, 0664);
+		if(savefd < 0){
+			fprint(2, "create: %r");
+			free(buf);
+			return;
+		}
+		back = emalloc(nback);
+		memset(back, 0, nback);
+		write(savefd, back, nback);
+		free(buf);
+		if((feat & FEATTIM) != 0){
+			timer.ns = nsec();
+			timersave(tim);
+			write(savefd, tim, TIMERSIZ);
+		}
+		atexit(flushback);
+		return;
+	}
+	back = emalloc(nback);
+	readn(savefd, back, nback);
+	if((feat & FEATTIM) != 0){
+		readn(savefd, tim, TIMERSIZ);
+		timerload(buf);
+	}
+	atexit(flushback);
+	free(buf);
+}
+
+void
+loadrom(char *file)
+{
+	int fd;
+	vlong sz;
+	static uchar nintendo[24] = {
+		0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83,
+		0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E
+	};
+	static u8int mbctab[31] = {
+		0, 1, 1, 1, -1, 2, 2, -1,
+		0, 0, -1, 6, 6, 6, -1, 3,
+		3, 3, 3, 3, -1, 4, 4, 4,
+		-1, 5, 5, 5, 5, 5, 5};
+	static u8int feattab[31] = {
+		0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT, 0,
+		FEATRAM, FEATRAM|FEATBAT, 0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATTIM|FEATBAT,
+		FEATTIM|FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT, 0, 0, FEATRAM, FEATRAM|FEATBAT,
+		0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT
+	};
 	
 	fd = open(file, OREAD);
 	if(fd < 0)
 		sysfatal("open: %r");
-	len = seek(fd, 0, 2);
-	if(len < 0)
-		sysfatal("seek: %r");
-	if(len == 0 || len > 16*1048576)
-		sysfatal("are you sure this is a ROM?");
-	cart = malloc(len);
-	if(cart == nil)
-		sysfatal("malloc: %r");
+	sz = seek(fd, 0, 2);
+	if(sz <= 0 || sz > 32*1024*1024)
+		sysfatal("invalid file size");
 	seek(fd, 0, 0);
-	if(readn(fd, cart, len) < len)
+	nrom = sz;
+	rom = emalloc(nrom);
+	if(readn(fd, rom, sz) < sz)
 		sysfatal("read: %r");
 	close(fd);
-
-	ck = 0;
-	for(i = 0x134; i <= 0x14C; i++)
-		ck -= cart[i] + 1;
-	if(ck != cart[0x14D])
-		sysfatal("checksum mismatch: %.2x != %.2x", ck, cart[0x14D]);
-	memcpy(mem, cart, 32768);
-	memset(title, 0, sizeof(title));
-	memcpy(title, cart+0x134, 16);
-	battery = 0;
-	switch(cart[0x147]){
-	case 0x09:
-		battery = 1;
-	case 0x08:
-		ramen = 1;
-	case 0x00:
-		mbc = 0;
-		break;
-	case 0x03:
-		battery = 1;
-	case 0x01: case 0x02:
-		mbc = 1;
-		break;
-	case 0x06:
-		battery = 1;
-	case 0x05:
-		mbc = 2;
-		break;
-	case 0x0F: case 0x10: case 0x13:
-		battery = 1;
-	case 0x11: case 0x12:
-		mbc = 3;
-		break;
-	case 0x1B: case 0x1E:
-		battery = 1;
-	case 0x19: case 0x1A: case 0x1C: case 0x1D:
-		mbc = 5;
-		break;
-	default:
-		sysfatal("%s: unknown cartridge type %.2x", file, cart[0x147]);
-	}
-
-	switch(cart[0x148]){
-	case 0: case 1: case 2:
-	case 3: case 4: case 5:
-	case 6: case 7:
-		rombanks = 2 << (uint)cart[0x148];
-		break;
-	case 52:
-		rombanks = 72;
-		break;
-	case 53:
-		rombanks = 80;
-		break;
-	case 54:
-		rombanks = 96;
-		break;
-	default:
-		sysfatal("header field 0x148 (%.2x) invalid", cart[0x148]);
-	}
-	switch(cart[0x149]){
-	case 0:
-		if(mbc != 2){
-			rambanks = 0;
+	if(memcmp(rom + 0x104, nintendo, 24) != 0)
+		sysfatal("not a gameboy rom");
+	if(rom[0x147] > 0x1f)
+		sysfatal("unsupported mapper ([0x147] = %.2ux)", rom[0x147]);
+	mbc = mbctab[rom[0x147]];
+	feat = feattab[rom[0x147]];
+	if((feat & FEATRAM) != 0){
+		switch(rom[0x149]){
+		case 0:
+			if(mbc == 2)
+				nback = 512;
+			else
+				feat &= ~FEATRAM;
 			break;
+		case 1: nback = 2048; break;
+		case 2: nback = 8192; break;
+		case 3: nback = 32768; break;
+		default: sysfatal("invalid ram size");
 		}
-		/*fallthrough*/
-	case 1: case 2:
-		rambanks = 1;
-		break;
-	case 3:
-		rambanks = 4;
-		break;
-	default:
-		sysfatal("header field 0x149 (%.2x) invalid", cart[0x149]);
 	}
-	if(rambanks > 0){
-		ram = mallocz(rambanks * 8192, 1);
-		if(ram == nil)
-			sysfatal("malloc: %r");
+	if(nback == 0)
+		nbackbank = 1;
+	else
+		nbackbank = nback + 8191 >> 13;
+	if((feat & (FEATRAM|FEATTIM)) == 0)
+		feat &= ~FEATBAT;
+	if((rom[0x143] & 0x80) != 0 && (mode & FORCEDMG) == 0)
+		mode = CGB|COL;
+	if((feat & FEATBAT) != 0)
+		loadsave(file);	
+	switch(mbc){
+	case 0: case 1: case 2: case 3: case 5: break;
+	default: sysfatal("unsupported mbc %d", mbc);
 	}
-	if(len < rombanks * 0x4000)
-		sysfatal("cartridge image is too small, %.4x < %.4x", (int)len, rombanks * 0x4000);
-	initdraw(nil, nil, title);
-	originwindow(screen, Pt(0, 0), screen->r.min);
+
+}
+
+void
+screeninit(void)
+{
+	Point p;
+
 	p = divpt(addpt(screen->r.min, screen->r.max), 2);
-	picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))};
+	picr = (Rectangle){subpt(p, Pt(scale * PICW/2, scale * PICH/2)), addpt(p, Pt(scale * PICW/2, scale * PICH/2))};
+	tmp = allocimage(display, Rect(0, 0, scale * PICW, scale > 1 ? 1 : scale * PICH), XRGB32, scale > 1, 0);
 	bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
-	tmp = allocimage(display, Rect(0, 0, scale * 160, scale * 144), XRGB32, 0, 0);
-	draw(screen, screen->r, bg, nil, ZP);
-	
-	if(ram && battery){
-		strncpy(buf, file, sizeof buf - 4);
-		s = buf + strlen(buf) - 3;
-		if(s < buf || strcmp(s, ".gb") != 0)
-			s += 3;
-		strcpy(s, ".gbs");
-		savefd = create(buf, ORDWR|OEXCL, 0666);
-		if(savefd < 0)
-			savefd = open(buf, ORDWR);
-		if(savefd < 0)
-			message("open: %r");
-		else
-			readn(savefd, ram, rambanks * 8192);
-		atexit(flushram);
-	}
+	draw(screen, screen->r, bg, nil, ZP);	
 }
 
 void
 keyproc(void *)
 {
-	int fd;
-	char buf[256], *s;
+	int fd, k;
+	static char buf[256];
+	char *s;
 	Rune r;
-	
+
 	fd = open("/dev/kbd", OREAD);
 	if(fd < 0)
 		sysfatal("open: %r");
 	for(;;){
-		if(read(fd, buf, 256) <= 0)
+		if(read(fd, buf, sizeof(buf) - 1) <= 0)
 			sysfatal("read /dev/kbd: %r");
 		if(buf[0] == 'c'){
-			if(utfrune(buf, Kdel))
-				threadexitsall(nil);
 			if(utfrune(buf, KF|5))
 				savereq = 1;
 			if(utfrune(buf, KF|6))
 				loadreq = 1;
+			if(utfrune(buf, Kdel)){
+				close(fd);
+				threadexitsall(nil);
+			}
+			if(utfrune(buf, 't'))
+				trace = !trace;
 		}
 		if(buf[0] != 'k' && buf[0] != 'K')
 			continue;
 		s = buf + 1;
-		keys = 0;
+		k = 0;
 		while(*s != 0){
 			s += chartorune(&r, s);
 			switch(r){
+			case Kdel: close(fd); threadexitsall(nil);
+			case 'z': k |= 1<<5; break;
+			case 'x': k |= 1<<4; break;
+			case Kshift: k |= 1<<6; break;
+			case 10: k |= 1<<7; break;
+			case Kup: k |= 1<<2; break;
+			case Kdown: k |= 1<<3; break;
+			case Kleft: k |= 1<<1; break;
+			case Kright: k |= 1<<0; break;
 			case Kesc:
 				if(paused)
 					qunlock(&pauselock);
@@ -198,156 +264,214 @@
 					qlock(&pauselock);
 				paused = !paused;
 				break;
-			case Kdel:
-				threadexitsall(nil);
-			case Kdown:
-				keys |= 1<<3;
+			case KF|1:	
+				if(paused){
+					qunlock(&pauselock);
+					paused=0;
+				}
+				framestep = !framestep;
 				break;
-			case Kup:
-				keys |= 1<<2;
-				break;
-			case Kleft:
-				keys |= 1<<1;
-				break;
-			case Kright:
-				keys |= 1<<0;
-				break;
-			case 'x':
-				keys |= 1<<4;
-				break;
-			case 'z':
-				keys |= 1<<5;
-				break;
-			case Kshift:
-				keys |= 1<<6;
-				break;
-			case 10:
-				keys |= 1<<7;
-				break;
 			}
 		}
+		k &= ~(k << 1 & 0x0a | k >> 1 & 0x05);
+		keys = k;
 	}
+
 }
 
 void
-threadmain(int argc, char** argv)
+timing(void)
 {
-	int t;
-
-	scale = 1;
-	ARGBEGIN{
-	case 'a':
-		initaudio();
-		break;
-	case '2':
-		scale = 2;
-		break;
-	case '3':
-		scale = 3;
-		break;
-	default:
-		sysfatal("unknown flag -%c", ARGC());
-	}ARGEND;
-	if(argc == 0)
-		sysfatal("argument missing");
-	pc = 0x100;
-	sp = 0xFFFE;
-	R[rA] = 0x01;
-	R[rC] = 0x13;
-	R[rE] = 0xD8;
-	R[rL] = 0x4D;
-	R[rH] = 0x01;
-	Fl = 0xB0;
-	loadrom(argv[0]);
-	mc = initmouse(nil, screen);
-	if(mc == nil)
-		sysfatal("init mouse: %r");
-	proccreate(keyproc, nil, 8192);
-	for(;;){
-		if(savereq){
-			savestate("gb.save");
-			savereq = 0;
-		}
-		if(loadreq){
-			loadstate("gb.save");
-			loadreq = 0;
-		}
-		if(paused){
-			qlock(&pauselock);
-			qunlock(&pauselock);
-		}
-		t = step();
-		clock += t;
-		ppuclock += t;
-		divclock += t;
-		audioclock += t;
-		timerclock += t;
-		if(ppuclock >= 456){
-			ppustep();
-			ppuclock -= 456;
-		}
-		if(divclock >= 256){
-			mem[DIV]++;
-			divclock = 0;
-		}
-		if(audioclock >= CPUFREQ / SAMPLE){
-			audiosample();
-			audioclock -= CPUFREQ / SAMPLE;
-		}
-		if(timer && timerclock >= timerfreq){
-			mem[TIMA]++;
-			if(mem[TIMA] == 0){
-				mem[TIMA] = mem[TMA];
-				interrupt(INTTIMER);
-			}
-			timerclock = 0;
-		}
-		if(msgclock > 0){
-			msgclock -= t;
-			if(msgclock <= 0){
-				draw(screen, screen->r, bg, nil, ZP);
-				msgclock = 0;
-			}
-		}
-	}
+	static int fcount;
+	static vlong old;
+	static char buf[32];
+	vlong new;
+	
+	if(++fcount == 60)
+		fcount = 0;
+	else
+		return;
+	new = nsec();
+	if(new != old)
+		sprint(buf, "%6.2f%%", 1e11 / (new - old));
+	else
+		buf[0] = 0;
+	draw(screen, rectaddpt(Rect(10, 10, 200, 30), screen->r.min), bg, nil, ZP);
+	string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, display->defaultfont, buf);
+	old = nsec();
 }
 
 void
 flush(void)
 {
-	extern uchar pic[160*144*4*3*3];
+	extern uchar pic[];
 	Mouse m;
-	Point p;
-	static vlong old;
+	static vlong old, delta;
 	vlong new, diff;
 
-	while(nbrecv(mc->c, &m) > 0)
-		;
 	if(nbrecvul(mc->resizec) > 0){
 		if(getwindow(display, Refnone) < 0)
 			sysfatal("resize failed: %r");
-		p = divpt(addpt(screen->r.min, screen->r.max), 2);
-		picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))};
-		if(bg->chan != screen->chan){
-			freeimage(bg);
-			bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
-		}
-		draw(screen, screen->r, bg, nil, ZP);
+		screeninit();
 	}
-	if(screen->chan != tmp->chan){
-		loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale);
+	while(nbrecv(mc->c, &m) > 0)
+		;
+	if(scale == 1){
+		loadimage(tmp, tmp->r, pic, PICW*PICH*4);
 		draw(screen, picr, tmp, nil, ZP);
-	}else
-		loadimage(screen, picr, pic, 160*144*4*scale*scale);
+	} else {
+		Rectangle r;
+		uchar *s;
+		int w;
+
+		s = pic;
+		r = picr;
+		w = PICW*4*scale;
+		while(r.min.y < picr.max.y){
+			loadimage(tmp, tmp->r, s, w);
+			s += w;
+			r.max.y = r.min.y+scale;
+			draw(screen, r, tmp, nil, ZP);
+			r.min.y = r.max.y;
+		}
+	}
 	flushimage(display, 1);
-	memset(pic, sizeof pic, 0);
+	if(profile)
+		timing();
 	if(audioout() < 0){
 		new = nsec();
+		diff = 0;
 		if(old != 0){
-			diff = BILLION/60 - (new - old);
+			diff = BILLION/60 - (new - old) - delta;
 			if(diff >= MILLION)
 				sleep(diff/MILLION);
 		}
 		old = nsec();
+		if(diff != 0){
+			diff = (old - new) - (diff / MILLION) * MILLION;
+			delta += (diff - delta) / 100;
+		}
+	}
+	if(framestep){
+		paused = 1;
+		qlock(&pauselock);
+		framestep = 0;
+	}
+	
+	if(saveframes > 0 && --saveframes == 0)
+		flushback();
+	if(savereq){
+		savestate("gb.save");
+		savereq = 0;
+	}
+	if(loadreq){
+		loadstate("gb.save");
+		loadreq = 0;
+	}
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-23aTcd] [-C col0,col1,col2,col3] rom\n", argv0);
+	exits("usage");
+}
+
+void
+colinit(void)
+{
+	int i;
+	union { u8int c[4]; u32int l; } c;
+	
+	c.c[3] = 0;
+	for(i = 0; i < 4; i++){
+		c.c[0] = c.c[1] = c.c[2] = i * 0x55;
+		moncols[i] = c.l;
+	}
+}
+
+void
+colparse(char *p)
+{
+	int i;
+	union { u8int c[4]; u32int l; } c;
+	u32int l;
+	
+	c.c[3] = 0;
+	for(i = 0; i < 4; i++){
+		l = strtol(p, &p, 16);
+		if(*p != (i == 3 ? 0 : ',') || l > 0xffffff)
+			usage();
+		p++;
+		c.c[0] = l;
+		c.c[1] = l >> 8;
+		c.c[2] = l >> 16;
+		moncols[i] = c.l;
+	}
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	int t;
+
+	colinit();
+	scale = 1;
+	ARGBEGIN {
+	case '2':
+		scale = 2;
+		break;
+	case '3':
+		scale = 3;
+		break;
+	case 'a':
+		audioinit();
+		break;
+	case 'T':
+		profile++;
+		break;
+	case 'c':
+		mode |= CGB;
+		break;
+	case 'd':
+		mode |= FORCEDMG;
+		break;
+	case 'C':
+		colparse(EARGF(usage()));
+		break;
+	default:
+		usage();
+	} ARGEND;
+	if(argc < 1)
+		usage();
+
+	loadrom(argv[0]);
+	
+	if(initdraw(nil, nil, nil) < 0)
+		sysfatal("initdraw: %r");
+	mc = initmouse(nil, screen);
+	if(mc == nil)
+		sysfatal("initmouse: %r");
+	proccreate(keyproc, nil, mainstacksize);
+	screeninit();
+
+	eventinit();
+	meminit();
+	ppuinit();
+	reset();
+	for(;;){
+		if(paused){
+			qlock(&pauselock);
+			qunlock(&pauselock);
+		}
+		if(dma > 0)
+			t = dmastep();
+		else
+			t = step();
+		if((mode & TURBO) == 0)
+			t += t;
+		clock += t;
+		if((elist->time -= t) <= 0)
+			popevent();
 	}
 }
--- a/sys/src/games/gb/mem.c
+++ b/sys/src/games/gb/mem.c
@@ -1,176 +1,569 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
-#include <draw.h>
 #include "dat.h"
 #include "fns.h"
 
-uchar mem[65536];
-int rombank, rambank, ramen, battery, ramrom;
-extern int savefd;
+u8int *rom;
+u8int *romb, *vramb, *wramb, *eramb;
+u8int wram[32768], vram[16384], oam[256], reg[256];
+u8int *back;
+u8int palm[128];
+u32int pal[64];
+int nrom, nback, nbackbank;
+u32int divclock;
+int prish;
+MBC3Timer timer, timerl;
+s8int dma;
+u32int white;
+u32int moncols[4];
 
+Var memvars[] = {ARR(wram), ARR(vram), ARR(oam), ARR(reg), ARR(palm), VAR(clock), VAR(divclock), VAR(mode), VAR(dma), {nil, 0, 0}};
+
 u8int
-memread(u16int p)
+regread(u8int a)
 {
-	extern int keys;
+	u8int v;
 
-	if((p & 0xFF80) == 0xFF00)
-		switch(p){
-		case 0xFF00:
-			if((mem[0xFF00] & (1<<5)) == 0)
-				return (mem[0xFF00] & 0xF0) | ~(keys >> 4);
-			if((mem[0xFF00] & (1<<6)) == 0)
-				return (mem[0xFF00] & 0xF0) | ~(keys & 0x0F);
-			return (mem[0xFF00] & 0xF0) | 0x0F;
-		}
-	if(!ramen && ((p & 0xE000) == 0xA000))
-		return 0xFF;
-	return mem[p];
+	switch(a){
+	case JOYP:
+		v = keys & 0x30 | 0xcf;
+		if((reg[a] & 0x10) == 0)
+			v &= 0xf0 | ~keys;
+		if((reg[a] & 0x20) == 0)
+			v &= 0xf0 | ~(keys >> 4);
+		return v;
+	case DIV:
+		return reg[DIV] + (clock - divclock >> 7 - ((mode & TURBO) != 0));
+	case TIMA:
+		return timread();
+	case STAT:
+		return reg[a] & 0xf8 | (reg[LYC] == ppuy) << 2 | ppustate;
+	case LY:
+		return ppuy;
+	case BCPD:
+		return palm[reg[BCPS] & 0x3f];
+	case OCPD:
+		return palm[0x40 | reg[OCPS] & 0x3f];
+	case NR13: case NR23: case NR31: case NR33: case NR41:
+		return 0xff;
+	case NR14: case NR24: case NR34: case NR44:
+		return reg[a] | 0xbf;
+	case NR52:
+		return apuread();
+	default:
+		if((a & 0xf0) == 0x30)
+			return waveread(a & 0xf);
+		return reg[a];
+	}
 }
 
+void
+colcol(int i, u16int v)
+{
+	union { u8int c[4]; u32int l; } c;
+
+	c.c[0] = v >> 7 & 0xf8;
+	c.c[1] = v >> 2 & 0xf8;
+	c.c[2] = v << 3;
+	c.c[3] = 0;
+	pal[i] = c.l;	
+}
+
+void
+regwrite(u8int a, u8int v)
+{
+	extern Event evhblank;
+	int i;
+	u8int u;
+
+	switch(a){
+	case DIV:
+		divclock = clock;
+		v = 0;
+		break;
+	case TIMA:
+		reg[a] = v;
+		timerset();
+		return;
+	case TAC:
+		v |= 0xf8;
+		timertac(v, 0);
+		break;
+	case STAT:
+		v |= 0x80;
+		if((v & IRQLYC) != 0 && ppuy == reg[LYC])
+			reg[IF] |= IRQLCDS;
+		break;
+	case LYC:
+		if((reg[STAT] & IRQLYC) != 0 && ppuy == v)
+			reg[IF] |= IRQLCDS;
+		break;
+	case LCDC:
+		ppusync();
+		if((~v & reg[a] & LCDEN) != 0)
+			delevent(&evhblank);
+		if((v & ~reg[a] & LCDEN) != 0)
+			addevent(&evhblank, 456*2);
+		break;
+	case SCY: case SCX: case WY: case WX:
+		ppusync();
+		break;
+	case VBK:
+		if((mode & COL) == 0)
+			break;
+		vramb = vram + ((v & 1) << 13);
+		v |= 0xfe;
+		break;
+	case SVBK:
+		if((mode & COL) == 0)
+			break;
+		v &= 7;
+		wramb = wram + (v + (v - 1 >> 3 & 1) << 12);
+		v |= 0xf8;
+		break;
+	case BGP:
+	case OBP0:
+	case OBP1:
+		if((mode & COL) != 0)
+			break;
+		ppusync();
+		i = a - BGP << 2;
+		pal[i] = moncols[~v & 3];
+		pal[i+1] = moncols[~v >> 2 & 3];
+		pal[i+2] = moncols[~v >> 4 & 3];
+		pal[i+3] = moncols[~v >> 6 & 3];
+		break;
+	case DMA:
+		for(i = 0; i < 160; i++)
+			oam[i] = memread(v << 8 | i);
+		break;
+	case BCPS: v |= 0x40; break;
+	case OCPS: v |= 0x40; break;
+	case BCPD:
+		if((mode & COL) == 0)
+			break;
+		ppusync();
+		u = reg[BCPS] & 0x3f;
+		palm[u] = v;
+		colcol(u / 2, palm[u & 0xfe] | palm[u | 1] << 8);
+		if((reg[BCPS] & 0x80) != 0)
+			reg[BCPS] = reg[BCPS] + 1 - (u + 1 & 0x40);
+		break;
+	case OCPD:
+		if((mode & COL) == 0)
+			break;
+		ppusync();
+		u = 0x40 | reg[OCPS] & 0x3f;
+		palm[u] = v;
+		colcol(u / 2, palm[u & 0xfe] | palm[u | 1] << 8);
+		if((reg[OCPS] & 0x80) != 0)
+			reg[OCPS] = reg[OCPS] + 1 - ((reg[OCPS] & 0x3f) + 1 & 0x40);
+		break;
+	case IF: v |= 0xe0; break;
+	case KEY1: v |= 0x7e; break;
+	case HDMAC:
+		if((mode & COL) == 0)
+			break;
+		dma = (v & 0x80) != 0 ? -1 : 1;
+		break;
+	case NR10: v |= 0x80; goto snd;
+	case NR14: case NR24: v |= 0x38; goto snd;
+	case NR32: v |= 0x9f; goto snd;
+	case NR41: v |= 0xc0; goto snd;
+	case NR44: v |= 0x3f; goto snd;
+	case NR52: v |= 0x70; goto snd;
+	case NR11: case NR12: case NR13:
+	case NR21: case NR22: case NR23:
+	case NR30: case NR31: case NR33: case NR34:
+	case NR42: case NR43:
+	case NR50: case NR51:
+	snd:
+		sndwrite(a, v);
+		break;
+	}
+	if((a & 0xf0) == 0x30)
+		wavewrite(a, v);
+	reg[a] = v;
+}
+
 static void
-ramswitch(int state, int bank)
+nope(int p)
 {
-	if(ramen){
-		memcpy(ram + 8192 * rambank, mem + 0xA000, 8192);
-		if(battery && savefd > 0){
-			seek(savefd, rambank * 8192, 0);
-			write(savefd, ram + 8192 * rambank, 8192);
+	print("unimplemented mapper function %d (mapper %d)\n", p, mbc);
+}
+
+static int
+mbc0(int a, int)
+{
+	if(a < 0)
+		switch(a){
+		case INIT:
+			if(nback != 0)
+				eramb = back;
+			return 0;
+		case SAVE:
+		case RSTR:
+			return 0;
+		case READ:
+			return -1;
+		default:
+			nope(a);
 		}
-		ramen = 0;
-	}
-	rambank = bank;
-	if(state){
-		if(bank >= rambanks)
-			sysfatal("invalid RAM bank %d selected (pc = %.4x)", bank, curpc);
-		memcpy(mem + 0xA000, ram + 8192 * rambank, 8192);
-		ramen = 1;
-	}
+	return 0;
 }
 
-void
-flushram(void)
+static int
+mbc1(int a, int v)
 {
+	static u8int ramen, b0, b1, romram;
+	static Var mbc1vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(romram), {nil, 0, 0}};
+	u16int b;
+
+	if(a < 0)
+		switch(a){
+		case INIT:
+			return 0;
+		case SAVE:
+			putvars(mbc1vars);
+			break;
+		case RSTR:
+			getvars(mbc1vars);
+			break;
+		case READ:
+			return -1;
+		default:
+			nope(a);
+		}
+	switch(a >> 13){
+	case 0: ramen = (v & 0xf) == 0xa; break;
+	case 1: v &= 0x1f; b0 = v != 0 ? v : 1; break;
+	case 2: b1 = v & 3; b1 %= nbackbank; break;
+	case 3: romram = v & 1; break;
+	}
+	b = b0;
+	if(!romram)
+		b |= b1 << 5;
+	b %= nrom >> 14;
+	romb = rom + (b << 14);
 	if(ramen)
-		ramswitch(ramen, rambank);
+		if(romram)
+			eramb = back + (b1 << 13);
+		else
+			eramb = back;
+	else
+		eramb = nil;
+	return 0;
 }
 
-static void
-romswitch(int bank)
+static int
+mbc2(int a, int v)
 {
-	if(bank >= rombanks)
-		sysfatal("invalid ROM bank %d selected (pc = %.4x)", bank, curpc);
-	rombank = bank;
-	memcpy(mem + 0x4000, cart + 0x4000 * bank, 0x4000);
+	static int ramen, b;
+	static Var mbc2vars[] = {VAR(ramen), VAR(b), {nil, 0, 0}};
+
+	if(a < 0)
+		switch(a){
+		case INIT:
+			return 0;
+		case SAVE:
+			putvars(mbc2vars);
+			return 0;
+		case RSTR:
+			getvars(mbc2vars);
+			romb = rom + (b << 14);
+			return 0;
+		case READ:
+			if(ramen)
+				return back[a & 0x1ff];
+			return 0xff;
+		default:
+			nope(a);
+		}
+	if((a & 0xc100) == 0)
+		ramen = (v & 0x0f) == 0x0a;
+	else if((a & 0xc100) == 0x100){
+		b = v & 0x0f;
+		if(b == 0)
+			b++;
+		b %= nrom >> 14;
+		romb = rom + (b << 14);
+	}else if((a >> 12) == 0xa && ramen)
+		back[a & 0x1ff] = v | 0xf0;
+	return 0;
 }
 
 void
-memwrite(u16int p, u8int v)
+timerforward(MBC3Timer *t)
 {
-	if(p < 0x8000){
-		switch(mbc){
-		case 0:
-			return;
-		case 1:
-		case 2:
-			switch(p >> 13){
-			case 0:
-				if((v & 0x0F) == 0x0A)
-					ramswitch(1, rambank);
-				else
-					ramswitch(0, rambank);
-				return;
-			case 1:
-				v &= 0x1F;
-				if(v == 0)
-					v++;
-				romswitch((rombank & 0xE0) | v);
-				return;
-			case 2:
-				if(ramrom)
-					ramswitch(ramen, v & 3);
-				else
-					romswitch(((v & 3) << 5) | (rombank & 0x1F));
-				return;
-			case 3:
-				ramrom = v;
-				return;
+	vlong n, nd;
+	int x;
+	
+	n = nsec();
+	nd = n - t->ns;
+	if(nd < 0)
+		return;
+	if((t->dh & 0x40) != 0){
+		t->ns = n;
+		return;
+	}
+	t->ns = n - nd % BILLION;
+	x = t->sec + t->min * 60 + t->hr * 3600 + t->dl * 86400 + t->dh * (256 * 86400);
+	x += nd / BILLION;
+	t->sec = x % 60;
+	x /= 60;
+	t->min = x % 60;
+	x /= 60;
+	t->hr = x % 24;
+	x /= 24;
+	t->dl = x & 0xff;
+	x >>= 8;
+	t->dh = t->dh & 0xfe | x & 1;
+	if(x >= 2) t->dh |= 0x80;
+}
+
+static int
+mbc3(int a, int v)
+{
+	static u8int ramen, b0, b1, latch;
+	static Var mbc3vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(latch),
+		VAR(timer.ns), VAR(timer.sec), VAR(timer.min), VAR(timer.hr), VAR(timer.dl), VAR(timer.dh),
+		VAR(timerl.sec), VAR(timerl.min), VAR(timerl.hr), VAR(timerl.dl), VAR(timerl.dh), {nil, 0, 0}};
+
+	if(a < 0)
+		switch(a){
+		case INIT:
+			return 0;
+		case SAVE:
+			putvars(mbc3vars);
+			return 0;
+		case RSTR:
+			getvars(mbc3vars);
+			romb = rom + (b0 << 14);
+			break;
+		case READ:
+			if(!ramen)
+				return -1;
+			switch(b1){
+			case 8: return timerl.sec;
+			case 9: return timerl.min;
+			case 10: return timerl.hr;
+			case 11: return timerl.dl;
+			case 12: return timerl.dh;
 			}
-			return;
-		case 3:
-			switch(p >> 13){
-			case 0:
-				if((v & 0x0F) == 0x0A)
-					ramswitch(1, rambank);
-				else
-					ramswitch(0, rambank);
-				return;
-			case 1:
-				v &= 0x7F;
-				if(v == 0)
-					v++;
-				romswitch(v);
-				return;
-			case 2:
-				if(v < 4)
-					ramswitch(ramen, v);
-				return;
-			}
-			return;
-		case 5:
-			switch(p >> 12){
-			case 0: case 1:
-				if((v & 0x0F) == 0x0A)
-					ramswitch(1, rambank);
-				else
-					ramswitch(0, rambank);
-				return;
-			case 2:
-				romswitch((rombank & 0x100) | v);
-				return;
-			case 3:
-				romswitch((((int)v & 1) << 8) | (rombank & 0xFF));
-				return;
-			case 4:
-				ramswitch(ramen, v & 15);
-				return;
-			
-			}
-			return;
+			return -1;
 		default:
-			sysfatal("mbc %d unimplemented", mbc);
+			nope(a);
 		}
+	switch(a >> 13){
+	case 0: ramen = (v & 0xf) == 0xa; break;
+	case 1:
+		v &= 0x7f;
+		b0 = v != 0 ? v : 1;
+		b0 %= nrom >> 14;
+		romb = rom + (b0 << 14);
+		return 0;
+	case 2: b1 = v & 15; b1 %= nbackbank; break;
+	case 3:
+		if(latch == 0 && v == 1){
+			timerl = timer;
+			timerforward(&timerl);
+		}
+		latch = v;
+		break;
+	case 0xa:
+		if(!ramen)
+			return 0;
+		switch(b1){
+		case 8: timerforward(&timer); timer.sec = v; break;
+		case 9: timerforward(&timer); timer.min = v; break;
+		case 10: timerforward(&timer); timer.hr = v; break;
+		case 11: timerforward(&timer); timer.dl = v; break;
+		case 12: timerforward(&timer); timer.dh = v; break;
+		}
+		return 0;
 	}
-	if((p & 0xFF80) == 0xFF00)
-		switch(p){
-		case 0xFF04:
-			v = 0;
+	eramb = ramen && b1 < 4 ? back + (b1 << 13) : nil;
+	return 0;
+}
+
+static int
+mbc5(int a, int v)
+{
+	static u8int ramen, b1;
+	static u16int b0;
+	static Var mbc5vars[] = {VAR(ramen), VAR(b0), VAR(b1), {nil, 0, 0}};
+
+	if(a < 0)
+		switch(a){
+		case INIT:
+			return 0;
+		case SAVE:
+			putvars(mbc5vars);
+			return 0;
+		case RSTR:
+			getvars(mbc5vars);
 			break;
-		case 0xFF07:
-			timer = (v & 4) != 0;
-			switch(v & 3){
-			case 0:
-				timerfreq = 1024;
-				break;
-			case 1:
-				timerfreq = 16;
-				break;
-			case 2:
-				timerfreq = 64;
-				break;
-			default:
-				timerfreq = 256;
-			}
-			break;
-		case 0xFF26:
-			v = (v & 0xF0) | (mem[p] & 0x0F);
-		case 0xFF41:
-			v &= ~7;
-			v |= mem[p] & 7;
-			break;
-		case 0xFF46:
-			memcpy(mem + 0xFE00, mem + (((int)v) << 8), 0xA0);
-			break;
+		case READ:
+			return -1;
+		default:
+			nope(a);
 		}
-	mem[p] = v;
+	switch(a >> 13){
+	case 0: ramen = (v & 0xf) == 0xa; break;
+	case 1: b0 = b0 & 0x100 | v; break;
+	case 2: b0 = b0 & 0xff | v << 8 & 0x100; break;
+	case 3: b1 = v & 0xff; b1 %= nbackbank; break;
+	}
+	b0 %= nrom >> 14;
+	romb = rom + (b0 << 14); 
+	eramb = ramen ? back + (b1 << 13) : nil;
+	return 0;
+	
+}
+
+int (*mappers[7])(int, int) = {mbc0, mbc1, mbc2, mbc3, mbc0, mbc5, mbc0};
+int (*mapper)(int, int);
+
+u8int
+memread(u16int a)
+{
+	switch(a >> 12){
+	case 0: case 1: case 2: case 3:
+		return rom[a];
+	case 4: case 5: case 6: case 7:
+		return romb[a - 0x4000];
+	case 8: case 9:
+		return vramb[a - 0x8000];
+	case 10: case 11:
+		if(eramb != nil)
+			return eramb[a - 0xa000];
+		return mapper(READ, a);
+	case 12: case 14:
+		return wram[a & 0xfff];
+	case 15:
+		if(a >= 0xff00)
+			return regread(a);
+		else if(a >= 0xfe00)
+			return oam[a - 0xfe00];
+	case 13:
+		return wramb[a & 0xfff];
+	}
+	return 0xff;
+}
+
+void
+memwrite(u16int a, u8int v)
+{
+	switch(a >> 12){
+	case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+		mapper(a, v);
+		return;
+	case 8: case 9:
+		vramb[a - 0x8000] = v;
+		return;
+	case 10: case 11:
+		if(eramb != nil)
+			eramb[a - 0xa000] = v;
+		else
+			mapper(a, v);
+		writeback();
+		return;
+	case 12: case 14:
+		wram[a & 0xfff] = v;
+		return;
+	case 15:
+		if(a >= 0xff00){
+			regwrite(a, v);
+			return;
+		}else if(a >= 0xfe00){
+			oam[a - 0xfe00] = v;
+			return;
+		}
+	case 13:
+		wramb[a & 0xfff] = v;
+	}
+}
+
+void
+meminit(void)
+{
+	union { u8int c[4]; u32int l; } c;
+
+	c.c[0] = c.c[1] = c.c[2] = 0;
+	c.c[3] = 1;
+	for(; c.l != 1; prish++)
+		c.l >>= 1;
+	
+	c.c[0] = c.c[1] = c.c[2] = 0xff;
+	c.c[3] = 0;
+	white = c.l;
+
+	romb = rom + 0x4000;
+	wramb = wram + 0x1000;
+	vramb = vram;
+	mapper = mappers[mbc];
+	mapper(INIT, 0);
+	
+	reg[LCDC] = 0x91;
+	reg[VBK] = 0xfe;
+	reg[SVBK] = 0xf8;
+	reg[IF] = 0xe0;
+}
+
+void
+memload(void)
+{
+	int i;
+	u8int v;
+
+	if((mode & COL) != 0){
+		for(i = 0; i < 64; i++)
+			colcol(i, palm[2*i] | palm[2*i+1] << 8);
+		vramb = vram + ((reg[VBK] & 1) << 13);
+		wramb = wram + (reg[SVBK] + (reg[SVBK] - 1 >> 3 & 1) << 12);
+	}else{
+		v = reg[BGP];
+		pal[0] = moncols[~v & 3];
+		pal[1] = moncols[~v >> 2 & 3];
+		pal[2] = moncols[~v >> 4 & 3];
+		pal[3] = moncols[~v >> 6 & 3];
+		v = reg[OBP0];
+		pal[4] = moncols[~v & 3];
+		pal[5] = moncols[~v >> 2 & 3];
+		pal[6] = moncols[~v >> 4 & 3];
+		pal[7] = moncols[~v >> 6 & 3];
+		v = reg[OBP1];
+		pal[8] = moncols[~v & 3];
+		pal[9] = moncols[~v >> 2 & 3];
+		pal[10] = moncols[~v >> 4 & 3];
+		pal[11] = moncols[~v >> 6 & 3];
+	}
+
+}
+
+int
+dmastep(void)
+{
+	int i;
+	u16int sa, da;
+	
+	sa = (reg[HDMASL] | reg[HDMASH] << 8) & 0xfff0;
+	da = (reg[HDMADL] | reg[HDMADH] << 8) & 0x0ff0;
+	for(i = 0; i < 16; i++)
+		memwrite(da++, memread(sa++));
+	reg[HDMASL] += 16;
+	if((reg[HDMASL] & 0xf0) == 0)
+		reg[HDMASH]++;
+	reg[HDMADL] += 16;
+	if((reg[HDMADL] & 0xf0) == 0)
+		reg[HDMADH]++;
+	if((reg[HDMAC] & 0x7f) == 0)
+		dma = 0;
+	else{
+		reg[HDMAC]--;
+		if((reg[HDMAC] & 0x80) != 0)
+			dma = 1;
+	}
+	return 64;
 }
--- a/sys/src/games/gb/mkfile
+++ b/sys/src/games/gb/mkfile
@@ -3,14 +3,13 @@
 BIN=/$objtype/bin/games
 TARG=gb
 OFILES=\
-	gb.$O\
 	cpu.$O\
 	mem.$O\
-	disasm.$O\
+	gb.$O\
 	ppu.$O\
-	daa.$O\
+	ev.$O\
 	state.$O\
-	audio.$O\
+	apu.$O\
 
 HFILES=dat.h fns.h
 
--- a/sys/src/games/gb/ppu.c
+++ b/sys/src/games/gb/ppu.c
@@ -1,217 +1,320 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
-#include <draw.h>
 #include "dat.h"
 #include "fns.h"
 
-uchar pic[160*144*4*9];
+u8int ppustate, ppuy;
+u32int pic[PICW*PICH];
+ulong hblclock, rendclock;
+jmp_buf mainjmp, renderjmp;
+static int cyc, done, ppux, ppux0;
+extern int prish;
+extern u32int white;
 
-static void
-resolvetile(u8int tx, u8int ty, u8int toy, int window, u8int* tnl1, u8int *tnl2)
-{
-	u16int tni, tnli;
-	u8int tn;
+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,
 	
-	tni = 0x9800 + 32 * ((u16int)ty) + ((u16int)tx);
-	if(window){
-		if(mem[LCDC] & WINDOWTILEMAP)
-			tni += 0x400;
-	}else
-		if(mem[LCDC] & BGTILEMAP)
-			tni += 0x400;
-	tn = mem[tni];
-	if(mem[LCDC] & BGTILEDATA)
-		tnli = 0x8000 + 16 * (u16int)tn;
-	else
-		tnli = 0x9000 + 16 * (u16int)(schar)tn;
-	*tnl1 = mem[tnli + 2 * ((u16int)toy)];
-	*tnl2 = mem[tnli + 2 * ((u16int)toy) + 1];
-}
+	TILCOL0 = 0x01,
+	TILPRI = 0x02,
+	TILSPR = 0x04,
+};
+sprite spr[10], *sprm;
 
-static void
-pixel(int x, int y, int val, int back)
+void
+ppurender(void)
 {
-	int Y;
-	union { u8int c[4]; u32int l; } u;
-	u32int *p, l;
-
-	val = (3 - val) * 0x55;
-	u.c[0] = val;
-	u.c[1] = val;
-	u.c[2] = val;
-	u.c[3] = back ? 0 : 0xFF;
-	l = u.l;
-	if(scale == 3){
-		p = ((u32int*)pic) + y * 3 * 3 * 160 + 3 * x;
-		for(Y = 0; Y < 3; Y++){
-			*p++ = l;
-			*p++ = l;
-			*p = l;
-			p += 3 * 160 - 2;
+	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 = 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 | ppuy - reg[WY] << 2 & 0x3e0;
+			y = ppuy - reg[WY] << 1 & 14;
+			cyc += 2;
+			m = 175 - reg[WX];
+			goto restart;
 		}
-	}else if(scale == 2){
-		p = ((u32int*)pic) + y * 2 * 2 * 160 + 2 * x;
-		*p++ = l;
-		*p = l;
-		p += 2 * 160 - 1;
-		*p++ = l;
-		*p = l;
-	}else{
-		p = ((u32int*)pic) + y * 160 + x;
-		*p = l;
+		done = 1;
+		ryield();
 	}
 }
 
-static void
-pixelbelow(int x, int y, int val)
+void
+oamsearch(void)
 {
-	if(pic[y*scale*scale*160*4 + x*scale*4 + 3] == 0)
-		pixel(x, y, val, 0);
-}
-
-static void
-drawbg(void)
-{
-	u8int Y, x, y, ty, toy, tx, tox, tnl1, tnl2, pal, val,h;
+	u8int *p;
+	sprite *q;
+	int y0, sy;
+	u8int t, tn;
+	u8int *chrp;
 	
-	Y = mem[LY];
-	y = Y + mem[SCY];
-	ty = y / 8;
-	toy = y % 8;
-	tx = mem[SCX] / 8;
-	tox = mem[SCX] % 8;
-	resolvetile(tx, ty, toy, 0, &tnl1, &tnl2);
-	tnl1 <<= (tox+1) % 8;
-	tnl2 <<= (tox+1) % 8;
-	pal = mem[BGP];
-	for(x = 0; x < 160; x++){
-		tox++;
-		if((tox % 8) == 0){
-			tx++;
-			resolvetile(tx%32, ty, toy, 0, &tnl1, &tnl2);
-		}
-		val = ((tnl1 & 0x80) >> 6) | ((tnl2 & 0x80) >> 5);
-		h = val == 0;
-		val = (pal >> val) & 3;
-		pixel(x, Y, val, h);
-		tnl1 <<= 1;
-		tnl2 <<= 1;
+	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;
 	}
 }
 
-static void
-drawsprites(void)
+void
+sprites(void)
 {
-	u8int y, t, tnl1, tnl2, dx, ddx, val, pal;
-	schar dy;
-	u16int tnli;
-	int i, x, big;
-	struct { u8int y, x, t, f; } *s;
+	sprite *q;
+	u8int attr;
+	u32int *picp;
+	int x, x1;
+	u16int chr;
 	
-	y = mem[LY];
-	big = mem[LCDC] & SPRITE16;
-	s = (void*)(mem + 0xFE00);
-	for(i = 0; i < 40; i++, s++){
-		if(s->y == 0 || s->x == 0)
+	picp = pic + ppuy * PICW;
+	for(q = spr; q < sprm; q++){
+		if(q->x <= ppux0 || q->x >= ppux + 8)
 			continue;
-		dy = y - s->y + 16;
-		if(dy < 0 || dy >= (big ? 16 : 8))
-			continue;
-		pal = (s->f & (1<<4)) ? mem[OBP1] : mem[OBP0];
-		if(s->f & (1<<6))
-			dy = (big ? 15 : 7) - dy;
-		t = s->t;
-		if(big){
-			if(dy >= 8){
-				t |= 1;
-				dy -= 8;
-			}else
-				t &= ~1;
-		}
-		tnli = 0x8000 + 2 * (u16int)dy + 16 * (u16int) t;
-		tnl1 = mem[tnli];
-		tnl2 = mem[tnli + 1];
-		x = s->x - 9;
-		for(dx = 0; dx < 8; dx++, x++){
-			ddx = dx;
-			if((s->f & (1<<5)) == 0)
-				ddx = 7 - dx;
-			val = ((tnl1 >> ddx) & 1) | (((tnl2 >> ddx) & 1) << 1);
-			if(x < 0 || val == 0)
-				continue;
-			val = (pal >> (2 * val)) & 3;
-			if(x >= 160)
-				break;
-			if(s->f & (1<<7))
-				pixelbelow(x, y, val);
+		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 & TILPRI) == 0 && ((q->t & SPRPRI) == 0 || (attr & TILCOL0) != 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
-				pixel(x, y, val, 0);
+				q->chr <<= 1;
 		}
 	}
+	ppux0 = ppux;
 }
 
-static void
-drawwindow(void)
+void
+ppusync(void)
 {
-	u8int wx, wy, Y, y, ty, toy, tx, tox, tnl1, tnl2, x, val, pal;
-	if(mem[WX] < 7)
+	if(ppustate != 3)
 		return;
-	wx = mem[WX] - 7;
-	wy = mem[WY];
-	Y = mem[LY];
-	if(Y < wy)
-		return;
-	y = Y - wy;
-	ty = y / 8;
-	toy = y % 8;
-	tx = 0;
-	tox = 0;
-	resolvetile(tx, ty, toy, 1, &tnl1, &tnl2);
-	pal = mem[BGP];
-	for(x = wx; x < 160; x++){
-		tox++;
-		if((tox & 7) == 0){
-			tx++;
-			resolvetile(tx, ty, toy, 1, &tnl1, &tnl2);
+	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(++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);
 		}
-		val = ((tnl1 & 0x80) >> 6) | ((tnl2 & 0x80) >> 5);
-		val = (pal >> val) & 3;
-		pixel(x, Y, val, 0);
-		tnl1 <<= 1;
-		tnl2 <<= 1;
+		if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
+			reg[IF] |= IRQLCDS;
+		break;
+	case 1:
+		hblclock = clock + evhblank.time;
+		if(++ppuy == 154){
+			ppuy = 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 < 0)
+			dma = 1;
+		break;
 	}
 }
 
 void
-ppustep(void)
+ppuinit(void)
 {
-	if(mem[LY] == 144){
-		mem[STAT] &= ~3;
-		mem[STAT] |= 1;
-		interrupt(INTVBLANK);
-	}
-	if(mem[LY] == mem[LYC]){
-		mem[STAT] |= 4;
-		if(mem[STAT] & 64)
-			interrupt(INTLCDC);
-	}else
-		mem[STAT] &= ~4;
-	if(mem[LY] < 144)
-		mem[STAT] &= ~3;
-	if(mem[LY] < 144 && (mem[LCDC] & LCDOP)){
-		if(mem[LCDC] & BGDISP)
-			drawbg();
-		if(mem[LCDC] & WINDOWDISP)
-			drawwindow();
-		if(mem[LCDC] & SPRITEDISP)
-			drawsprites();
-	}
-	mem[LY]++;
-	if(mem[LY] > 160){
-		mem[LY] = 0;
-		if((mem[LCDC] & LCDOP) == 0)
-			memset(pic, 0, sizeof(pic));
-		flush();
-	}
+	static char ppustack[4096];
+	
+	renderjmp[JMPBUFPC] = (uintptr)ppurender;
+	renderjmp[JMPBUFSP] = (uintptr)(ppustack + sizeof(ppustack) - 64);
+	myield();
 }
--- a/sys/src/games/gb/state.c
+++ b/sys/src/games/gb/state.c
@@ -2,124 +2,163 @@
 #include <libc.h>
 #include <thread.h>
 #include <draw.h>
+#include <bio.h>
 #include "dat.h"
 #include "fns.h"
 
-static int fd;
+extern Var cpuvars[], ppuvars[], memvars[], apuvars[], evvars[];
+extern Event *events[NEVENT], *elist;
+static Biobuf *bp;
+Var apuvars[] = {{nil, 0, 0}};
 
 static void
-put8(u8int i)
+putevents(void)
 {
-	write(fd, &i, 1);
+	int i, j;
+	Event *e;
+	
+	for(i = 0; i < NEVENT; i++)
+		if(elist == events[i])
+			break;
+	if(i == NEVENT && elist != nil)
+		print("unknown event %p in chain\n", elist);
+	Bputc(bp, i);
+	for(i = 0; i < NEVENT; i++){
+		e = events[i];
+		Bputc(bp, e->time);
+		Bputc(bp, e->time >> 8);
+		Bputc(bp, e->time >> 16);
+		Bputc(bp, e->time >> 24);
+		for(j = 0; j < NEVENT; j++)
+			if(e->next == events[j])
+				break;
+		if(j == NEVENT && e->next != nil)
+			print("unknown event %p in chain\n", e->next);
+		Bputc(bp, j);
+	}
+		
 }
 
 static void
-put16(u16int i)
+getevents(void)
 {
-	put8(i);
-	put8(i >> 8);
+	int i, j;
+	Event *e;
+	
+	i = Bgetc(bp);
+	elist = i >= NEVENT ? nil : events[i];
+	for(i = 0; i < NEVENT; i++){
+		e = events[i];
+		e->time = Bgetc(bp);
+		e->time |= Bgetc(bp) << 8;
+		e->time |= Bgetc(bp) << 16;
+		e->time |= Bgetc(bp) << 24;
+		j = Bgetc(bp);
+		e->next = j >= NEVENT ? nil : events[j];
+	}
 }
 
-static void
-put32(u32int i)
+void
+getvars(Var *v)
 {
-	put8(i);
-	put8(i >> 8);
-	put8(i >> 16);
-	put8(i >> 24);
-}
+	int n;
+	u16int *p, w;
+	u32int *q, l;
 
-static int
-get8(void)
-{
-	u8int c;
-	
-	read(fd, &c, 1);
-	return c;
-}
+	for(; v->a != nil; v++)
+		switch(v->s){
+		case 1:
+			Bread(bp, v->a, v->n);
+			break;
+		case 2:
+			n = v->n;
+			p = v->a;
+			while(n--){
+				w = Bgetc(bp);
+				*p++ = w | Bgetc(bp) << 8;
+			}
+			break;
+		case 4:
+			n = v->n;
+			q = v->a;
+			while(n--){
+				l = Bgetc(bp);
+				l |= Bgetc(bp) << 8;
+				l |= Bgetc(bp) << 16;
+				*q++ = l | Bgetc(bp) << 24;
+			}
+			break;
+		}
 
-static int
-get16(void)
-{
-	int i;
-	
-	i = get8();
-	i |= get8() << 8;
-	return i;
 }
 
-static int
-get32(void)
+void
+putvars(Var *v)
 {
-	int i;
-	
-	i = get8();
-	i |= get8() << 8;
-	i |= get8() << 16;
-	i |= get8() << 24;
-	return i;
+	int n;
+	u16int *p;
+	u32int *q;
+
+	for(; v->a != nil; v++)
+		switch(v->s){
+		case 1:
+			Bwrite(bp, v->a, v->n);
+			break;
+		case 2:
+			n = v->n;
+			p = v->a;
+			while(n--){
+				Bputc(bp, *p & 0xff);
+				Bputc(bp, *p++ >> 8);
+			}
+			break;
+		case 4:
+			n = v->n;
+			q = v->a;
+			while(n--){
+				Bputc(bp, *q);
+				Bputc(bp, *q >> 8);
+				Bputc(bp, *q >> 16);
+				Bputc(bp, *q++ >> 24);
+			}
+			break;
+		}
 }
 
 void
-loadstate(char *file)
+savestate(char *file)
 {
-	flushram();
-	fd = open(file, OREAD);
-	if(fd < 0){
-		message("open: %r");
+	flushback();
+	bp = Bopen(file, OWRITE);
+	if(bp == nil){
+		print("open: %r\n");
 		return;
 	}
-	read(fd, mem, 65536);
-	if(ram != nil)
-		read(fd, ram, rambanks * 8192);
-	read(fd, R, sizeof R);
-	sp = get16();
-	pc = get16();
-	Fl = get8();
-	halt = get32();
-	IME = get32();
-	clock = get32();
-	ppuclock = get32();
-	divclock = get32();
-	timerclock = get32();
-	timerfreq = get32();
-	timer = get32();
-	rombank = get32();
-	rambank = get32();
-	ramen = get32();
-	battery = get32();
-	ramrom = get32();
-	close(fd);
+	putvars(cpuvars);
+	putvars(ppuvars);
+	putvars(memvars);
+	putvars(apuvars);
+	putvars(evvars);
+	putevents();
+	mapper(SAVE, 0);
+	Bterm(bp);
 }
 
 void
-savestate(char *file)
+loadstate(char *file)
 {
-	flushram();
-	fd = create(file, ORDWR, 0666);
-	if(fd < 0){
-		message("create: %r");
+	bp = Bopen(file, OREAD);
+	if(bp == nil){
+		print("open: %r\n");
 		return;
 	}
-	write(fd, mem, 65536);
-	if(ram != nil)
-		write(fd, ram, rambanks * 8192);
-	write(fd, R, sizeof R);
-	put16(sp);
-	put16(pc);
-	put8(Fl);
-	put32(halt);
-	put32(IME);
-	put32(clock);
-	put32(ppuclock);
-	put32(divclock);
-	put32(timerclock);
-	put32(timerfreq);
-	put32(timer);
-	put32(rombank);
-	put32(rambank);
-	put32(ramen);
-	put32(battery);
-	put32(ramrom);
-	close(fd);
+	getvars(cpuvars);
+	getvars(ppuvars);
+	getvars(memvars);
+	getvars(apuvars);
+	getvars(evvars);
+	getevents();
+	mapper(RSTR, 0);
+	memload();
+	Bterm(bp);
 }