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);