15 int keys, paused, framestep, backup;
17 int savefd, saveframes;
21 char *biosfile = "/sys/games/lib/gbabios.bin";
30 sysfatal("malloc: %r");
31 setmalloctag(v, getcallerpc(&sz));
46 pwrite(savefd, back, nback, BACKTYPELEN);
53 extern uchar bios[16384];
57 fd = open(biosfile, OREAD);
60 readn(fd, bios, 16384);
68 union {char a[4]; u32int u;} s1 = {"EEPR"}, s2 = {"SRAM"}, s3 = {"FLAS"};
74 if(v == s1.u && memcmp(p - 1, "EEPROM_V", 8) == 0){
75 print("backup type is either eeprom4 or eeprom64 -- can't detect which one\n");
78 if(v == s2.u && memcmp(p - 1, "SRAM_V", 6) == 0){
83 if(memcmp(p - 1, "FLASH_V", 7) == 0 || memcmp(p - 1, "FLASH512_V", 10) == 0){
87 if(memcmp(p - 1, "FLASH1M_V", 9) == 0){
97 parsetype(char *s, int *size)
99 if(strcmp(s, "eeprom4") == 0){
102 }else if(strcmp(s, "eeprom64") == 0){
105 }else if(strcmp(s, "sram256") == 0){
108 }else if(strcmp(s, "flash512") == 0){
111 }else if(strcmp(s, "flash1024") == 0){
119 typename(char *s, int type, int size)
133 sysfatal("typestr: unknown type %d -- shouldn't happen", type);
136 snprint(s, BACKTYPELEN, "%s%d", st, size/128);
143 char tstr[BACKTYPELEN];
146 buf = emalloc(strlen(file) + 4);
148 p = strchr(buf, '.');
150 p = buf + strlen(buf);
152 savefd = open(buf, ORDWR);
154 if(backup == NOBACK){
155 backup = romtype(&nback);
156 if(backup == NOBACK){
157 fprint(2, "failed to autodetect save format\n");
162 savefd = create(buf, OWRITE, 0664);
164 fprint(2, "create: %r");
168 memset(tstr, 0, sizeof(tstr));
169 typename(tstr, backup, nback);
170 write(savefd, tstr, sizeof(tstr));
171 back = emalloc(nback);
172 memset(back, 0, nback);
173 write(savefd, back, nback);
178 readn(savefd, tstr, sizeof(tstr));
180 type = parsetype(tstr, &size);
181 if(type == NOBACK || backup != NOBACK && (type != backup || nback != size))
182 sysfatal("%s: invalid format", buf);
185 back = emalloc(nback);
186 readn(savefd, back, nback);
197 fd = open(file, OREAD);
199 sysfatal("open: %r");
201 if(sz <= 0 || sz > 32*1024*1024)
202 sysfatal("invalid file size");
206 if(readn(fd, rom, sz) < sz)
207 sysfatal("read: %r");
210 if(nrom == 32*KB*KB && backup == EEPROM)
219 p = divpt(addpt(screen->r.min, screen->r.max), 2);
220 picr = (Rectangle){subpt(p, Pt(scale * 120, scale * 80)), addpt(p, Pt(scale * 120, scale * 80))};
221 tmp = allocimage(display, Rect(0, 0, scale * 240, scale > 1 ? 1 : scale * 160), CHAN4(CIgnore, 1, CBlue, 5, CGreen, 5, CRed, 5), scale > 1, 0);
222 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
223 draw(screen, screen->r, bg, nil, ZP);
230 static char buf[256];
234 fd = open("/dev/kbd", OREAD);
236 sysfatal("open: %r");
240 memmove(buf, buf+n, sizeof(buf)-n);
243 n = read(fd, buf, sizeof(buf)-1);
245 sysfatal("read /dev/kbd: %r");
250 if(utfrune(buf, KF|5))
252 if(utfrune(buf, KF|6))
254 if(utfrune(buf, Kdel)){
258 if(utfrune(buf, 't'))
261 if(buf[0] != 'k' && buf[0] != 'K')
266 s += chartorune(&r, s);
268 case Kdel: close(fd); threadexitsall(nil);
269 case 'z': k |= 1<<1; break;
270 case 'x': k |= 1<<0; break;
271 case 'a': k |= 1<<9; break;
272 case 's': k |= 1<<8; break;
273 case Kshift: k |= 1<<2; break;
274 case 10: k |= 1<<3; break;
275 case Kup: k |= 1<<6; break;
276 case Kdown: k |= 1<<7; break;
277 case Kleft: k |= 1<<5; break;
278 case Kright: k |= 1<<4; break;
291 framestep = !framestep;
295 k &= ~(k << 1 & 0xa0 | k >> 1 & 0x50);
315 sprint(buf, "%6.2f%%", 1e11 / (new - old));
318 draw(screen, rectaddpt(Rect(10, 10, 200, 30), screen->r.min), bg, nil, ZP);
319 string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, display->defaultfont, buf);
329 static vlong old, delta;
332 if(nbrecvul(mc->resizec) > 0){
333 if(getwindow(display, Refnone) < 0)
334 sysfatal("resize failed: %r");
337 while(nbrecv(mc->c, &m) > 0)
340 loadimage(tmp, tmp->r, pic, 240*160*2);
341 draw(screen, picr, tmp, nil, ZP);
350 while(r.min.y < picr.max.y){
351 loadimage(tmp, tmp->r, s, w);
353 r.max.y = r.min.y+scale;
354 draw(screen, r, tmp, nil, ZP);
358 flushimage(display, 1);
365 diff = BILLION/60 - (new - old) - delta;
371 diff = (old - new) - (diff / MILLION) * MILLION;
372 delta += (diff - delta) / 100;
381 if(saveframes > 0 && --saveframes == 0)
384 if((reg[KEYCNT] & 1<<14) != 0){
385 x = reg[KEYCNT] & keys;
386 if((reg[KEYCNT] & 1<<15) != 0){
387 if(x == (reg[KEYCNT] & 0x3ff))
398 fprint(2, "usage: %s [-23aT] [-s savetype] [-b biosfile] rom\n", argv0);
403 threadmain(int argc, char **argv)
421 backup = parsetype(s, &nback);
423 sysfatal("unknown save type '%s'", s);
426 biosfile = strdup(EARGF(usage()));
440 if(initdraw(nil, nil, nil) < 0)
441 sysfatal("initdraw: %r");
442 mc = initmouse(nil, screen);
444 sysfatal("initmouse: %r");
445 proccreate(keyproc, nil, mainstacksize);
453 savestate("gba.save");
457 loadstate("gba.save");
471 if((elist->time -= t) <= 0)