10 extern uchar ppuram[16384];
16 int clock, ppuclock, syncclock, syncfreq, checkclock, sleeps;
19 extern void (*mapper[])(int, u8int);
27 static uchar header[16];
30 fd = open(file, OREAD);
33 if(readn(fd, header, sizeof(header)) < sizeof(header))
35 if(memcmp(header, "NES\x1a", 4) != 0)
36 sysfatal("not a ROM");
38 memset(header + 7, 0, 9);
39 flags = header[6] | header[7] << 8;
40 nes20 = (flags & FLNES20M) == FLNES20V;
41 if(flags & (FLVS | FLPC10))
42 sysfatal("ROM not supported");
45 nprg |= (header[HROMH] & 0xf) << 8;
47 sysfatal("invalid ROM");
50 nchr |= (header[HROMH] & 0xf0) << 4;
51 map = (flags >> FLMAPPERL) & 0x0f | (((flags >> FLMAPPERH) & 0x0f) << 4);
53 map |= (header[8] & 0x0f) << 8;
54 if(map >= 256 || mapper[map] == nil)
55 sysfatal("unimplemented mapper %d", map);
57 memset(mem, 0, sizeof(mem));
58 if((flags & FLTRAINER) != 0 && readn(fd, mem + 0x7000, 512) < 512)
60 prg = malloc(nprg * PRGSZ);
62 sysfatal("malloc: %r");
63 if(readn(fd, prg, nprg * PRGSZ) < nprg * PRGSZ)
66 chr = malloc(nchr * CHRSZ);
68 sysfatal("malloc: %r");
69 if(readn(fd, chr, nchr * CHRSZ) < nchr * CHRSZ)
73 chr = malloc(16 * CHRSZ);
75 sysfatal("malloc: %r");
77 if((flags & FLFOUR) != 0)
79 else if((flags & FLMIRROR) != 0)
93 fd = open("/dev/kbd", OREAD);
97 if(read(fd, buf, 256) <= 0)
98 sysfatal("read /dev/kbd: %r");
100 if(utfrune(buf, Kdel))
103 if(buf[0] != 'k' && buf[0] != 'K')
108 s += chartorune(&r, s);
110 case Kdel: threadexitsall(nil);
111 case 'x': keys |= 1<<0; break;
112 case 'z': keys |= 1<<1; break;
113 case Kshift: keys |= 1<<2; break;
114 case 10: keys |= 1<<3; break;
115 case Kup: keys |= 1<<4; break;
116 case Kdown: keys |= 1<<5; break;
117 case Kleft: keys |= 1<<6; break;
118 case Kright: keys |= 1<<7; break;
125 threadmain(int argc, char **argv)
129 uvlong old, new, diff;
142 sysfatal("missing argument");
144 if(initdraw(nil, nil, nil) < 0)
145 sysfatal("initdraw: %r");
146 mc = initmouse(nil, screen);
148 sysfatal("initmouse: %r");
149 proccreate(keyproc, nil, 8192);
150 originwindow(screen, Pt(0, 0), screen->r.min);
151 p = divpt(addpt(screen->r.min, screen->r.max), 2);
152 picr = (Rectangle){subpt(p, Pt(scale * 128, scale * 120)), addpt(p, Pt(scale * 128, scale * 120))};
153 if(screen->chan != XRGB32)
154 tmp = allocimage(display, Rect(0, 0, scale * 256, scale * 240), XRGB32, 0, 0);
155 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
156 draw(screen, screen->r, bg, nil, ZP);
158 pc = memread(0xFFFC) | memread(0xFFFD) << 8;
160 syncfreq = FREQ / 30;
168 while(ppuclock >= 4){
172 if(syncclock >= syncfreq){
177 if(checkclock >= FREQ){
179 diff = new - old - sleeps * 10 * MILLION;
180 diff = BILLION - diff;
184 syncfreq = ((vlong)FREQ) * 10 * MILLION / diff;
185 if(syncfreq < FREQ / 100)
186 syncfreq = FREQ / 100;