shithub: riscv

Download patch

ref: 744f038e86aef8f30b3c7abead3be5d30e163a2c
parent: 0c9a1e665368101371c4dc32c6bebbc879baa8b3
author: aiju <devnull@localhost>
date: Sat Mar 15 17:46:00 EDT 2014

games/snes: mode 7

--- a/sys/src/games/snes/dat.h
+++ b/sys/src/games/snes/dat.h
@@ -10,9 +10,11 @@
 extern u8int reg[32768], spcmem[65536], vram[65536], oam[544];
 extern u16int cgram[256];
 
-extern int ppux, ppuy;
+extern int ppux, ppuy, rx;
 extern u16int vtime, htime, subcolor, oamaddr;
-extern u16int m7[6], hofs[4], vofs[4];
+extern u16int hofs[5], vofs[5];
+typedef signed short s16int;
+extern s16int m7[6];
 
 extern int battery, saveclock, scale, mouse;
 
@@ -43,6 +45,7 @@
 	OAMADDH = 0x2103,
 	BGMODE = 0x2105,
 	MOSAIC = 0x2106,
+	M7SEL = 0x211a,
 	WIN1 = 2,
 	INVW1 = 1,
 	WIN2 = 8,
@@ -55,6 +58,7 @@
 	CGADSUB = 0x2131,
 	DIRCOL = 1,
 	SETINI = 0x2133,
+	EXTBG = 1<<6,
 	OVERSCAN = 1<<2,
 	AUTOJOY = 1,
 	NMITIMEN = 0x4200,
--- a/sys/src/games/snes/mem.c
+++ b/sys/src/games/snes/mem.c
@@ -21,6 +21,8 @@
 	OPVCTH,
 };
 
+extern void calc7(void);
+
 static void
 incvram(int i, int r)
 {
@@ -220,15 +222,29 @@
 			oam[oamaddr & 0x21f] = v;
 		oamaddr = (oamaddr + 1) & 0x3ff;
 		return;
-	case 0x210d: case 0x210f:
-	case 0x2111: case 0x2113:
+	case 0x2105:
+		reg[p] = v;
+		calc7();
+		return;
+	case 0x210d:
+		hofs[4] = (v & 0x1f) << 8 | reg[M7PREV];
+		if((v & 0x10) != 0)
+			hofs[4] |= 0xe000;
+		reg[M7PREV] = v;
+		calc7();
+	case 0x210f: case 0x2111: case 0x2113:
 		a = (p - 0x210d) >> 1;
-		hofs[a] = (v << 8) | reg[OFSPREV] & ~7 | (hofs[a] >> 8) & 7;
+		hofs[a] = v << 8 | reg[OFSPREV] & ~7 | (hofs[a] >> 8) & 7;
 		reg[OFSPREV] = v;
 		break;
-	case 0x210e: case 0x2110:
-	case 0x2112: case 0x2114:
-		vofs[(p - 0x210e) >> 1] = (v << 8) | reg[OFSPREV];
+	case 0x210e:
+		vofs[4] = (v & 0x1f) << 8 | reg[M7PREV];
+		if((v & 0x10) != 0)
+			vofs[4] |= 0xe000;
+		reg[M7PREV] = v;
+		calc7();
+	case 0x2110: case 0x2112: case 0x2114:
+		vofs[(p - 0x210e) >> 1] = v << 8 | reg[OFSPREV];
 		reg[OFSPREV] = v;
 		break;
 	case 0x2116:
@@ -248,8 +264,14 @@
 		return;
 	case 0x211b: case 0x211c: case 0x211d:
 	case 0x211e: case 0x211f: case 0x2120:
-		m7[p - 0x211b] = (v << 8) | reg[M7PREV];
+		m7[p - 0x211b] = v << 8 | reg[M7PREV];
+		if(p >= 0x211f)
+			if((v & 0x10) != 0)
+				m7[p - 0x211b] |= 0xe000;
+			else
+				m7[p - 0x211b] &= 0x1fff;
 		reg[M7PREV] = v;
+		calc7();
 		break;
 	case 0x2121:
 		reg[CGLH] = 0;
--- a/sys/src/games/snes/ppu.c
+++ b/sys/src/games/snes/ppu.c
@@ -9,8 +9,18 @@
 static u32int pixelcol[2];
 u16int vtime = 0x1ff, htime = 0x1ff, subcolor, mosatop;
 uchar pic[256*239*2*9];
-u16int m7[6], hofs[4], vofs[4];
+u16int hofs[5], vofs[5];
+s16int m7[6];
 
+enum {
+	M7A,
+	M7B,
+	M7C,
+	M7D,
+	M7X,
+	M7Y
+};
+
 enum { OBJ = 4, COL = 5, OBJNC = 8 };
 
 static u16int
@@ -311,7 +321,114 @@
 		chr(n, p->nb, p->sz, p->t, p->tnx, p->tny, p->c);
 }
 
+struct bg7ctxt {
+	int x, y, x0, y0;
+	u8int msz, mx, mv;
+} b7[2];
+
+void
+calc7(void)
+{
+	s16int t;
+
+	if((reg[0x2105] & 7) != 7)
+		return;
+	t = hofs[4] - m7[M7X];
+	if((t & 0x2000) != 0)
+		t |= ~0x3ff;
+	else
+		t &= 0x3ff;
+	b7->x0 = (t * m7[M7A]) & ~63;
+	b7->y0 = (t * m7[M7C]) & ~63;
+	t = vofs[4] - m7[M7Y];
+	if((t & 0x2000) != 0)
+		t |= ~0x3ff;
+	else
+		t &= 0x3ff;
+	b7->x0 += (t * m7[M7B]) & ~63;
+	b7->y0 += (t * m7[M7D]) & ~63;
+	b7->x0 += m7[M7X] << 8;
+	b7->y0 += m7[M7Y] << 8;
+}
+
 static void
+bg7init(int n)
+{
+	u8int m, y;
+	struct bg7ctxt *p;
+	
+	p = b7 + n;
+	m = reg[M7SEL];
+	y = ppuy;
+	p->msz = 1;
+	if((reg[MOSAIC] & 1) != 0){
+		p->msz = (reg[MOSAIC] >> 4) + 1;
+		if(p->msz != 1)
+			y -= y % p->msz;
+	}
+	if(n == 1 && (reg[MOSAIC] & 2) != 0)
+		p->msz = (reg[MOSAIC] >> 4) + 1;
+	if((m & 2) != 0)
+		y = 255 - y;
+	p->x = b7->x0 + ((m7[M7B] * y) & ~63);
+	p->y = b7->y0 + ((m7[M7D] * y) & ~63);
+	if((m & 1) != 0){
+		p->x += 255 * m7[M7A];
+		p->y += 255 * m7[M7C];
+	}
+}
+
+static void
+bg7(int n)
+{
+	u16int x, y;
+	u8int m, v, t;
+	struct bg7ctxt *p;
+
+	p = b7 + n;
+	m = reg[M7SEL];
+	x = p->x >> 8;
+	y = p->y >> 8;
+	if((m & 0x80) == 0){
+		x &= 1023;
+		y &= 1023;
+	}else if(x > 1023 || y > 1023){
+		if((m & 0x40) != 0){
+			t = 0;
+			goto lookup;
+		}
+		v = 0;
+		goto end;
+	}
+	t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
+lookup:
+	v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
+end:
+	if(p->msz != 1){
+		if(p->mx == 0)
+			p->mv = v;
+		else
+			v = p->mv;
+		if(++p->mx == p->msz)
+			p->mx = 0;
+	}
+	if(n == 1)
+		if((v & 0x80) != 0)
+			pixel(1, v & 0x7f, 0x71);
+		else
+			pixel(1, v, 0x11);
+	else
+		pixel(0, v, 0x40);
+	if((m & 1) != 0){
+		p->x -= m7[M7A];
+		p->y -= m7[M7C];
+	}else{
+		p->x += m7[M7A];
+		p->y += m7[M7C];
+	}
+}
+
+static void
 bgsinit(void)
 {
 	static int bitch[8];
@@ -336,6 +453,11 @@
 		bginit(0, 8, 0x40, 0xa0);
 		bginit(1, 4, 0x11, 0x71);
 		break;
+	case 7:
+		bg7init(0);
+		if((reg[SETINI] & EXTBG) != 0)
+			bg7init(1);
+		break;
 	default:
 		bgctxts[0].sz = bgctxts[1].sz = 0;
 		if(bitch[mode]++ == 0)
@@ -362,6 +484,11 @@
 	case 3:
 		bg(0);
 		bg(1);
+		break;
+	case 7:
+		bg7(0);
+		if((reg[SETINI] & EXTBG) != 0)
+			bg7(1);
 		break;
 	}
 }
--- a/sys/src/games/snes/spc.c
+++ b/sys/src/games/snes/spc.c
@@ -442,6 +442,7 @@
 	if(trace)
 		print("SPC %.4x %.2x A=%.2x X=%.2x Y=%.2x P=%.2x S=%.2x\n", spc-1, op, sA, sX, sY, sP, sS);
 	switch(op){
+	case 0x00: return 2;
 	case 0x01: jsr(mem16(0xffde)); return 8;
 	case 0x02: setb(azp(), 0); return 4;
 	case 0x03: return branch((zp() & 0x01) != 0, 5);