12 int savefd = -1, saveframes;
14 u8int mbc, feat, mode;
15 extern MBC3Timer timer, timerl;
39 timer.ns = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24 | (uvlong)buf[4] << 32 | (uvlong)buf[5] << 40 | (uvlong)buf[6] << 48LL | (uvlong)buf[7] << 56LL;
56 buf[1] = timer.ns >> 8;
57 buf[2] = timer.ns >> 16;
58 buf[3] = timer.ns >> 24;
59 buf[4] = timer.ns >> 32;
60 buf[5] = timer.ns >> 40;
61 buf[6] = timer.ns >> 48;
62 buf[7] = timer.ns >> 56;
81 pwrite(savefd, back, nback, 0);
83 pwrite(savefd, buf, TIMERSIZ, nback);
94 buf = emalloc(strlen(file) + 4);
96 p = strrchr(buf, '.');
98 p = buf + strlen(buf);
100 savefd = open(buf, ORDWR);
102 savefd = create(buf, OWRITE, 0664);
104 fprint(2, "create: %r");
108 back = emalloc(nback);
109 memset(back, 0, nback);
110 write(savefd, back, nback);
112 if((feat & FEATTIM) != 0){
115 write(savefd, tim, TIMERSIZ);
120 back = emalloc(nback);
121 readn(savefd, back, nback);
122 if((feat & FEATTIM) != 0){
123 readn(savefd, tim, TIMERSIZ);
135 static uchar nintendo[24] = {
136 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83,
137 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E
139 static u8int mbctab[31] = {
140 0, 1, 1, 1, -1, 2, 2, -1,
141 0, 0, -1, 6, 6, 6, -1, 3,
142 3, 3, 3, 3, -1, 4, 4, 4,
143 -1, 5, 5, 5, 5, 5, 5};
144 static u8int feattab[31] = {
145 0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT, 0,
146 FEATRAM, FEATRAM|FEATBAT, 0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATTIM|FEATBAT,
147 FEATTIM|FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT, 0, 0, FEATRAM, FEATRAM|FEATBAT,
148 0, 0, FEATRAM, FEATRAM|FEATBAT, 0, FEATRAM, FEATRAM|FEATBAT
151 fd = open(file, OREAD);
153 sysfatal("open: %r");
155 if(sz <= 0 || sz > 32*1024*1024)
156 sysfatal("invalid file size");
160 if(readn(fd, rom, sz) < sz)
161 sysfatal("read: %r");
163 if(memcmp(rom + 0x104, nintendo, 24) != 0)
164 sysfatal("not a gameboy rom");
165 if(rom[0x147] > 0x1f)
166 sysfatal("unsupported mapper ([0x147] = %.2ux)", rom[0x147]);
167 mbc = mbctab[rom[0x147]];
168 feat = feattab[rom[0x147]];
169 if((feat & FEATRAM) != 0){
177 case 1: nback = 2048; break;
178 case 2: nback = 8192; break;
179 case 3: nback = 32768; break;
180 default: sysfatal("invalid ram size");
186 nbackbank = nback + 8191 >> 13;
187 if((feat & (FEATRAM|FEATTIM)) == 0)
189 if((rom[0x143] & 0x80) != 0 && (mode & FORCEDMG) == 0)
191 if((feat & FEATBAT) != 0)
194 case 0: case 1: case 2: case 3: case 5: break;
195 default: sysfatal("unsupported mbc %d", mbc);
204 static vlong old, delta;
208 flushaudio(audioout);
209 if(saveframes > 0 && --saveframes == 0)
212 savestate("gb.save");
216 loadstate("gb.save");
224 fprint(2, "usage: %s [-23aTcd] [-C col0,col1,col2,col3] rom\n", argv0);
232 union { u8int c[4]; u32int l; } c;
235 for(i = 0; i < 4; i++){
236 c.c[0] = c.c[1] = c.c[2] = i * 0x55;
245 union { u8int c[4]; u32int l; } c;
249 for(i = 0; i < 4; i++){
250 l = strtol(p, &p, 16);
251 if(*p != (i == 3 ? 0 : ',') || l > 0xffffff)
262 threadmain(int argc, char **argv)
278 colparse(EARGF(usage()));
287 initemu(PICW, PICH, 4, XRGB32, 1, nil);
288 regkey("b", 'z', 1<<5);
289 regkey("a", 'x', 1<<4);
290 regkey("control", Kshift, 1<<6);
291 regkey("start", '\n', 1<<7);
292 regkey("up", Kup, 1<<2);
293 regkey("down", Kdown, 1<<3);
294 regkey("left", Kleft, 1<<1);
295 regkey("right", Kright, 1<<0);
296 regkeyfn(KF|9, tauup);
297 regkeyfn(KF|10, taudn);
312 if((mode & TURBO) == 0)
315 if((elist->time -= t) <= 0)