10 char *bindir = "/sys/lib/c64";
11 Image *tmp, *bg, *red;
12 Rectangle picr, progr;
20 uchar *tape, tapever, tapeplay;
25 progress(int a, int b)
32 draw(screen, progr, bg, nil, ZP);
37 w = a * Dx(progr) / b;
40 draw(screen, Rect(progr.min.x, progr.min.y, progr.min.x + w, progr.max.y), red, nil, ZP);
45 loadsys(char *name, u8int *p, int n)
50 snprint(buf, sizeof(buf), "%s/%s", bindir, name);
51 fd = open(buf, OREAD);
54 if(readn(fd, p, n) < n)
55 sysfatal("readn: %r");
64 fd = open(name, OREAD);
67 nrom = seek(fd, 0, 2);
69 sysfatal("large ROM not supported");
70 if((nrom & nrom-1) != 0)
71 sysfatal("non-power-of-two ROM size");
74 sysfatal("malloc: %r");
75 pread(fd, rom, nrom, 0);
86 fd = open(name, OREAD);
90 if(memcmp(buf, "C64 CARTRIDGE ", 16) != 0)
91 sysfatal("not a c64 cartridge");
92 t = buf[0x16] << 8 | buf[0x17];
94 sysfatal("unsupported type %d", t);
95 if(buf[0x18] == 0) pla &= ~EXROM;
96 if(buf[0x19] == 0) pla &= ~GAME;
97 t = buf[0x4c] << 8 | buf[0x4d];
98 if(t < 0x8000 || t >= 0xc000 && t < 0xe000)
99 sysfatal("odd starting address %x", t);
103 l = buf[0x4e] << 8 | buf[0x4f];
105 sysfatal("cart too large");
106 read(fd, cart + t, l);
116 fd = open(name, OREAD);
118 sysfatal("open: %r");
120 if(memcmp(buf, "C64-TAPE-RAW", 12) != 0)
121 sysfatal("not a c64 raw tape");
124 sysfatal("unsupported tape version %d", tapever);
125 tapelen = buf[16] | buf[17] << 8 | buf[18] << 16 | buf[19] << 24;
126 tape = malloc(tapelen);
127 readn(fd, tape, tapelen);
134 int fd, i, n, setnmi;
137 static Rune keymap[64] = {
138 Kbs, '\n', Kleft, KF|7, KF|1, KF|3, KF|5, Kup,
139 '3', 'w', 'a', '4', 'z', 's', 'e', Kshift,
140 '5', 'r', 'd', '6', 'c', 'f', 't', 'x',
141 '7', 'y', 'g', '8', 'b', 'h', 'u', 'v',
142 '9', 'i', 'j', '0', 'm', 'k', 'o', 'n',
143 '\'', 'p', 'l', '-', '.', '\\', '@', ',',
144 '[', '*', ';', Khome, Kalt, '=', ']', '/',
145 '1', Kins, '\t', '2', ' ', Kctl, 'q', Kdel
147 static char buf[256];
151 fd = open("/dev/kbd", OREAD);
153 sysfatal("open: %r");
157 memmove(buf, buf+n, sizeof(buf)-n);
160 n = read(fd, buf, sizeof(buf)-1);
162 sysfatal("read /dev/kbd: %r");
167 if(utfrune(buf, Kend)){
171 if(utfrune(buf, KF|12))
174 if(buf[0] != 'k' && buf[0] != 'K')
181 s += chartorune(&r, s);
183 case Kend: close(fd); threadexitsall(nil);
194 case Kleft: if(joymode) j |= 1<<2+5*(joymode-1); break;
195 case Kright: if(joymode) j |= 1<<3+5*(joymode-1); break;
196 case Kup: if(joymode) j |= 1<<0+5*(joymode-1); break;
197 case Kdown: if(joymode) j |= 1<<1+5*(joymode-1); break;
198 case Kctl: if(joymode) j |= 1<<4+5*(joymode-1); break;
200 for(i = 0; i < 64; i++)
219 p = divpt(addpt(screen->r.min, screen->r.max), 2);
220 picr = (Rectangle){subpt(p, Pt(picw/2*scale, pich/2*scale)), addpt(p, Pt(picw/2*scale, pich/2*scale))};
221 p.y += pich*scale*3/4;
222 q = Pt(Dx(screen->r) * 2/5, 8);
223 progr = (Rectangle){subpt(p, q), addpt(p, q)};
225 tmp = allocimage(display, Rect(0, 0, picw*scale, scale > 1 ? 1 : pich), XRGB32, 1, 0);
226 draw(screen, screen->r, bg, nil, ZP);
232 fprint(2, "usage: %s [ -23a ] [ rom ]\n", argv0);
237 threadmain(int argc, char **argv)
251 loadcart(EARGF(usage()));
254 loadtape(EARGF(usage()));
263 bindir = strdup(EARGF(usage()));
270 loadsys("kernal.bin", krom, 8192);
271 loadsys("basic.bin", brom, 8192);
272 loadsys("crom.bin", crom, 4096);
276 if(initdraw(nil, nil, nil) < 0)
277 sysfatal("initdraw: %r");
278 mc = initmouse(nil, screen);
280 sysfatal("initmouse: %r");
281 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
282 red = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xFF0000FF);
284 proccreate(keyproc, nil, mainstacksize);
287 pc = memread(0xFFFC) | memread(0xFFFD) << 8;
302 static char joystr[32] = "joy: none";
303 static char tapestr[32] = "tape: play";
304 static char *items[] = {
313 switch(menuhit(3, mc, &m, nil)){
315 joymode = (joymode + 1) % 3;
317 strcpy(joystr, "joy: none");
319 sprint(joystr, "joy: %d", joymode);
324 strcpy(tapestr, "tape: play");
327 strcpy(tapestr, "tape: stop");
337 // static vlong old, delta;
339 if(nbrecvul(mc->resizec) > 0){
340 if(getwindow(display, Refnone) < 0)
341 sysfatal("resize failed: %r");
344 while(nbrecv(mc->c, &mc->Mouse) > 0)
345 if((mc->buttons & 4) != 0)
348 loadimage(tmp, tmp->r, pic, picw*pich*4);
349 draw(screen, picr, tmp, nil, ZP);
358 while(r.min.y < picr.max.y){
359 loadimage(tmp, tmp->r, s, w);
361 r.max.y = r.min.y+scale;
362 draw(screen, r, tmp, nil, ZP);
366 flushimage(display, 1);
372 diff = BILLION/60 - (new - old) - delta;
378 diff = (old - new) - (diff / MILLION) * MILLION;
379 delta += (diff - delta) / 100;