shithub: riscv

Download patch

ref: 8d11fd6d274a0792ebb64dcc89e2b8c087888fab
parent: e8e04281402b697c0568ce5e35dbd7fc1d0c0935
author: aiju <devnull@localhost>
date: Fri Mar 14 12:49:52 EDT 2014

games/snes: mouse support

--- a/sys/src/games/snes/dat.h
+++ b/sys/src/games/snes/dat.h
@@ -6,7 +6,7 @@
 
 extern uchar *prg, *sram;
 extern int nprg, nsram, keys;
-extern u16int keylatch;
+extern u32int keylatch, lastkeys;
 extern u8int reg[32768], spcmem[65536], vram[65536], oam[544];
 extern u16int cgram[256];
 
@@ -14,7 +14,7 @@
 extern u16int vtime, htime, subcolor, oamaddr;
 extern u16int m7[6], hofs[4], vofs[4];
 
-extern int battery, saveclock, scale;
+extern int battery, saveclock, scale, mouse;
 
 enum {
 	FLAGC = 1<<0,
--- a/sys/src/games/snes/mem.c
+++ b/sys/src/games/snes/mem.c
@@ -8,7 +8,8 @@
 u8int mem[131072];
 u8int oam[544], vram[65536];
 u16int cgram[256];
-u16int oamaddr, vramlatch, keylatch;
+u16int oamaddr, vramlatch;
+u32int keylatch, lastkeys;
 enum {
 	OAMLATCH,
 	CGLATCH,
@@ -62,6 +63,31 @@
 	return (a & 0x83e0) | (a & 0x7c00) >> 10 | (a & 0x001f) << 10;
 }
 
+static void
+mouselatch(void)
+{
+	int x, y;
+	u32int v;
+	
+	v = keys & 0xffff0000;
+	x = (keys & 0xff) - (lastkeys & 0xff);
+	y = (keys >> 8 & 0xff) - (lastkeys >> 8 & 0xff);
+	if(x < 0){
+		v |= 0x80;
+		x = -x;
+	}
+	if(y < 0){
+		v |= 0x8000;
+		y = -y;
+	}
+	if(x > 127)
+		x = 127;
+	if(y > 127)
+		y = 127;
+	keylatch = v | x | y << 8;
+	lastkeys = keys;
+}
+
 u8int
 regread(u16int p)
 {
@@ -124,9 +150,15 @@
 		reg[0x2181]++;
 		return v;
 	case 0x4016:
-		if((reg[0x4016] & 1) != 0)
-			return keylatch >> 15;
-		v = keylatch >> 15;
+		if((reg[0x4016] & 1) != 0){
+			if(mouse)
+				if((keys & 0x300000) == 0x300000)
+					keys &= ~0x300000;
+				else
+					keys += 0x100000;
+			return keys >> 31;
+		}
+		v = keylatch >> 31;
 		keylatch = (keylatch << 1) | 1;
 		return v;
 	case 0x4017:
@@ -235,8 +267,12 @@
 	case 0x213e:
 		return;
 	case 0x4016:
-		if((reg[0x4016] & 1) != 0 && (v & 1) == 0)
-			keylatch = keys;
+		if((reg[0x4016] & 1) != 0 && (v & 1) == 0){
+			if(mouse)
+				mouselatch();
+			else
+				keylatch = keys;
+		}
 		break;
 	case 0x4200:
 		if((reg[0x4200] & 0x80) == 0 && (v & 0x80) != 0 && (reg[RDNMI] & 0x80) != 0)
--- a/sys/src/games/snes/ppu.c
+++ b/sys/src/games/snes/ppu.c
@@ -579,9 +579,11 @@
 			if((reg[NMITIMEN] & VBLANK) != 0)
 				nmi = 2;
 			if((reg[NMITIMEN] & AUTOJOY) != 0){
-				reg[0x4218] = keys;
-				reg[0x4219] = keys >> 8;
-				keylatch = 0xffff;
+				memwrite(0x4016, 1);
+				memwrite(0x4016, 0);
+				reg[0x4218] = keylatch >> 16;
+				reg[0x4219] = keylatch >> 24;
+				keylatch = keylatch << 16 | 0xffff;
 			}
 		}
 		if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)
--- a/sys/src/games/snes/snes.c
+++ b/sys/src/games/snes/snes.c
@@ -15,7 +15,7 @@
 Mousectl *mc;
 QLock pauselock;
 int keys, savefd;
-int scale, profile;
+int scale, profile, mouse;
 Rectangle picr;
 Image *tmp, *bg;
 
@@ -126,23 +126,23 @@
 		if(buf[0] != 'k' && buf[0] != 'K')
 			continue;
 		s = buf + 1;
-		k = 0;
+		k = 0xffff;
 		while(*s != 0){
 			s += chartorune(&r, s);
 			switch(r){
 			case Kdel: close(fd); threadexitsall(nil);
-			case 'z': k |= 1<<15; break;
-			case 'x': k |= 1<<7; break;
-			case 'a': k |= 1<<14; break;
-			case 's': k |= 1<<6; break;
-			case 'q': k |= 1<<5; break;
-			case 'w': k |= 1<<4; break;
-			case Kshift: k |= 1<<13; break;
-			case 10: k |= 1<<12; break;
-			case Kup: k |= 1<<11; break;
-			case Kdown: k |= 1<<10; break;
-			case Kleft: k |= 1<<9; break;
-			case Kright: k |= 1<<8; break;
+			case 'z': k |= 1<<31; break;
+			case 'x': k |= 1<<23; break;
+			case 'a': k |= 1<<30; break;
+			case 's': k |= 1<<22; break;
+			case 'q': k |= 1<<21; break;
+			case 'w': k |= 1<<20; break;
+			case Kshift: k |= 1<<29; break;
+			case 10: k |= 1<<28; break;
+			case Kup: k |= 1<<27; break;
+			case Kdown: k |= 1<<26; break;
+			case Kleft: k |= 1<<25; break;
+			case Kright: k |= 1<<24; break;
 			case Kesc:
 				if(paused)
 					qunlock(&pauselock);
@@ -152,7 +152,8 @@
 				break;
 			}
 		}
-		keys = k;
+		if(!mouse)
+			keys = k;
 	}
 }
 
@@ -203,6 +204,10 @@
 	case 's':
 		battery++;
 		break;
+	case 'm':
+		mouse++;
+		keys = 1<<16;
+		break;
 	case 'T':
 		profile++;
 		break;
@@ -272,14 +277,26 @@
 {
 	extern uchar pic[256*240*2*9];
 	Mouse m;
+	Point p;
 
-	while(nbrecv(mc->c, &m) > 0)
-		;
 	if(nbrecvul(mc->resizec) > 0){
 		if(getwindow(display, Refnone) < 0)
 			sysfatal("resize failed: %r");
 		screeninit();
 	}
+	while(nbrecv(mc->c, &m) > 0)
+		if(mouse && ptinrect(m.xy, picr)){
+			p = subpt(m.xy, picr.min);
+			p.x /= scale;
+			p.y /= scale;
+			keys = keys & 0xff3f0000 | p.x | p.y << 8;
+			if((m.buttons & 1) != 0)
+				keys |= 1<<22;
+			if((m.buttons & 4) != 0)
+				keys |= 1<<23;
+			if((m.buttons & 2) != 0)
+				lastkeys = keys;
+		}
 	loadimage(tmp, tmp->r, pic, 256*239*2*scale*scale);
 	draw(screen, picr, tmp, nil, ZP);
 	flushimage(display, 1);