12 int nprg, nsram, hirom, battery;
14 int ppuclock, spcclock, dspclock, stimerclock, saveclock, msgclock, paused, perfclock, cpupause;
18 int savefd, scale, profile, mouse, loadreq, savereq;
26 pwrite(savefd, sram, nsram, 0);
36 fd = open(file, OREAD);
39 size = seek(fd, 0, 2);
43 sysfatal("empty file");
44 if((size & 1023) == 512){
47 }else if((size & 1023) == 0)
50 sysfatal("invalid rom size");
51 if(size >= 16*1048576)
52 sysfatal("rom too big");
53 nprg = (size + 32767) / 32768;
54 prg = malloc(nprg * 32768);
56 sysfatal("malloc: %r");
57 if(readn(fd, prg, size) < size)
62 if((memread(0xffd5) & ~0x10) != 0x20)
63 if((memread(0x1ffd5) & ~0x10) == 0x21)
66 sysfatal("invalid rom (ffd5 = %.2x, 1ffd5 = %.2x)", memread(0xffd5), memread(0x1ffd5));
70 switch(memread(0xffd6)){
76 nsram = memread(0xffd8);
80 sysfatal("invalid rom (too much ram specified)");
81 nsram = 1<<(nsram + 10);
84 sysfatal("malloc: %r");
87 print("unknown rom type %d\n", memread(0xffd5));
97 if(battery && nsram != 0){
98 strncpy(buf, file, sizeof buf - 5);
99 s = buf + strlen(buf) - 4;
100 if(s < buf || strcmp(s, ".smc") != 0)
103 savefd = create(buf, ORDWR | OEXCL, 0666);
105 savefd = open(buf, ORDWR);
109 readn(savefd, sram, nsram);
118 static char buf[256];
122 fd = open("/dev/kbd", OREAD);
124 sysfatal("open: %r");
126 if(read(fd, buf, sizeof(buf) - 1) <= 0)
127 sysfatal("read /dev/kbd: %r");
129 if(utfrune(buf, KF|5))
131 if(utfrune(buf, KF|6))
133 if(utfrune(buf, Kdel)){
137 if(utfrune(buf, 't'))
140 if(buf[0] != 'k' && buf[0] != 'K')
145 s += chartorune(&r, s);
147 case Kdel: close(fd); threadexitsall(nil);
148 case 'z': k |= 1<<31; break;
149 case 'x': k |= 1<<23; break;
150 case 'a': k |= 1<<30; break;
151 case 's': k |= 1<<22; break;
152 case 'q': k |= 1<<21; break;
153 case 'w': k |= 1<<20; break;
154 case Kshift: k |= 1<<29; break;
155 case 10: k |= 1<<28; break;
156 case Kup: k |= 1<<27; break;
157 case Kdown: k |= 1<<26; break;
158 case Kleft: k |= 1<<25; break;
159 case Kright: k |= 1<<24; break;
179 originwindow(screen, Pt(0, 0), screen->r.min);
180 p = divpt(addpt(screen->r.min, screen->r.max), 2);
181 picr = (Rectangle){subpt(p, Pt(scale * 128, scale * 112)), addpt(p, Pt(scale * 128, scale * 112))};
182 tmp = allocimage(display, Rect(0, 0, scale * 256, scale * 239), RGB15, 0, 0);
183 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
184 draw(screen, screen->r, bg, nil, ZP);
196 sprint(buf, "%6.2f%%", 1e11 / (new - old));
199 draw(screen, Rect(10, 10, 200, 30), bg, nil, ZP);
200 string(screen, Pt(10, 10), display->black, ZP, display->defaultfont, buf);
205 threadmain(int argc, char **argv)
241 fprint(2, "usage: %s [-23s] rom\n", argv0);
242 threadexitsall("usage");
245 if(initdraw(nil, nil, nil) < 0)
246 sysfatal("initdraw: %r");
247 mc = initmouse(nil, screen);
249 sysfatal("initmouse: %r");
252 proccreate(keyproc, 0, 8192);
259 savestate("snes.save");
263 loadstate("snes.save");
281 while(ppuclock >= 4){
286 spcclock += spcstep() * SPCDIV;
287 if(stimerclock >= SPCDIV*16){
289 stimerclock -= SPCDIV*16;
291 if(dspclock >= SPCDIV){
303 draw(screen, screen->r, bg, nil, ZP);
307 if(profile && perfclock <= 0){
317 extern uchar pic[256*240*2*9];
321 if(nbrecvul(mc->resizec) > 0){
322 if(getwindow(display, Refnone) < 0)
323 sysfatal("resize failed: %r");
326 while(nbrecv(mc->c, &m) > 0)
327 if(mouse && ptinrect(m.xy, picr)){
328 p = subpt(m.xy, picr.min);
331 keys = keys & 0xff3f0000 | p.x | p.y << 8;
332 if((m.buttons & 1) != 0)
334 if((m.buttons & 4) != 0)
336 if((m.buttons & 2) != 0)
339 loadimage(tmp, tmp->r, pic, 256*239*2*scale*scale);
340 draw(screen, picr, tmp, nil, ZP);
341 flushimage(display, 1);
346 message(char *fmt, ...)
349 static char buf[512];
352 vsnprint(buf, sizeof buf, fmt, va);
353 string(screen, Pt(10, 10), display->black, ZP, display->defaultfont, buf);