11 char *bindir = "/sys/lib/c64";
17 uchar *tape, tapever, tapeplay;
22 progress(int a, int b)
30 draw(screen, progr, bg, nil, ZP);
35 w = a * Dx(progr) / b;
38 draw(screen, Rect(progr.min.x, progr.min.y, progr.min.x + w, progr.max.y), red, nil, ZP);
43 loadsys(char *name, u8int *p, int n)
48 snprint(buf, sizeof(buf), "%s/%s", bindir, name);
49 fd = open(buf, OREAD);
52 if(readn(fd, p, n) < n)
53 sysfatal("readn: %r");
62 fd = open(name, OREAD);
65 nrom = seek(fd, 0, 2);
67 sysfatal("large ROM not supported");
68 if((nrom & nrom-1) != 0)
69 sysfatal("non-power-of-two ROM size");
72 sysfatal("malloc: %r");
73 pread(fd, rom, nrom, 0);
84 fd = open(name, OREAD);
88 if(memcmp(buf, "C64 CARTRIDGE ", 16) != 0)
89 sysfatal("not a c64 cartridge");
90 t = buf[0x16] << 8 | buf[0x17];
92 sysfatal("unsupported type %d", t);
93 if(buf[0x18] == 0) pla &= ~EXROM;
94 if(buf[0x19] == 0) pla &= ~GAME;
95 t = buf[0x4c] << 8 | buf[0x4d];
96 if(t < 0x8000 || t >= 0xc000 && t < 0xe000)
97 sysfatal("odd starting address %x", t);
101 l = buf[0x4e] << 8 | buf[0x4f];
103 sysfatal("cart too large");
104 read(fd, cart + t, l);
114 fd = open(name, OREAD);
116 sysfatal("open: %r");
118 if(memcmp(buf, "C64-TAPE-RAW", 12) != 0)
119 sysfatal("not a c64 raw tape");
122 sysfatal("unsupported tape version %d", tapever);
123 tapelen = buf[16] | buf[17] << 8 | buf[18] << 16 | buf[19] << 24;
124 tape = malloc(tapelen);
125 readn(fd, tape, tapelen);
132 int fd, i, n, setnmi;
135 static Rune keymap[64] = {
136 Kbs, '\n', Kleft, KF|7, KF|1, KF|3, KF|5, Kup,
137 '3', 'w', 'a', '4', 'z', 's', 'e', Kshift,
138 '5', 'r', 'd', '6', 'c', 'f', 't', 'x',
139 '7', 'y', 'g', '8', 'b', 'h', 'u', 'v',
140 '9', 'i', 'j', '0', 'm', 'k', 'o', 'n',
141 '\'', 'p', 'l', '-', '.', '\\', '@', ',',
142 '[', '*', ';', Khome, Kalt, '=', ']', '/',
143 '1', Kins, '\t', '2', ' ', Kctl, 'q', Kdel
145 static char buf[256];
149 fd = open("/dev/kbd", OREAD);
151 sysfatal("open: %r");
155 memmove(buf, buf+n, sizeof(buf)-n);
158 n = read(fd, buf, sizeof(buf)-1);
160 sysfatal("read /dev/kbd: %r");
165 if(utfrune(buf, Kend)){
169 if(utfrune(buf, KF|12))
172 if(buf[0] != 'k' && buf[0] != 'K')
179 s += chartorune(&r, s);
181 case Kend: close(fd); threadexitsall(nil);
192 case Kleft: if(joymode) j |= 1<<2+5*(joymode-1); break;
193 case Kright: if(joymode) j |= 1<<3+5*(joymode-1); break;
194 case Kup: if(joymode) j |= 1<<0+5*(joymode-1); break;
195 case Kdown: if(joymode) j |= 1<<1+5*(joymode-1); break;
196 case Kctl: if(joymode) j |= 1<<4+5*(joymode-1); break;
198 for(i = 0; i < 64; i++)
215 fprint(2, "usage: %s [ -23a ] [ rom ]\n", argv0);
220 threadmain(int argc, char **argv)
226 loadcart(EARGF(usage()));
229 loadtape(EARGF(usage()));
238 bindir = strdup(EARGF(usage()));
245 loadsys("kernal.bin", krom, 8192);
246 loadsys("basic.bin", brom, 8192);
247 loadsys("crom.bin", crom, 4096);
250 initemu(picw, pich, 4, XRGB32, 1, keyproc);
251 red = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xFF0000FF);
254 pc = memread(0xFFFC) | memread(0xFFFD) << 8;
269 static char joystr[32] = "joy: none";
270 static char tapestr[32] = "tape: play";
271 static char *items[] = {
281 switch(menuhit(3, mc, &m, nil)){
283 joymode = (joymode + 1) % 3;
285 strcpy(joystr, "joy: none");
287 sprint(joystr, "joy: %d", joymode);
292 strcpy(tapestr, "tape: play");
295 strcpy(tapestr, "tape: stop");
305 while(nbrecv(mc->c, &mc->Mouse) > 0)
306 if((mc->buttons & 4) != 0)