diff options
author | qwx <devnull@localhost> | 2018-05-12 19:20:53 +0200 |
---|---|---|
committer | qwx <devnull@localhost> | 2018-05-12 19:20:53 +0200 |
commit | 1195ca910c393e542d6aa23035fa75719af1107e (patch) | |
tree | c53f3d829d787834610367a9c4d41b5d29dcbb25 /sys/src | |
parent | 70c7a9eb07516843da083b6231d55a07d28b9350 (diff) |
add libemu
move redundant code from emulators to a common library
Diffstat (limited to 'sys/src')
37 files changed, 657 insertions, 1230 deletions
diff --git a/sys/src/games/c64/c64.c b/sys/src/games/c64/c64.c index c20333760..9b4e0504b 100644 --- a/sys/src/games/c64/c64.c +++ b/sys/src/games/c64/c64.c @@ -4,18 +4,15 @@ #include <draw.h> #include <mouse.h> #include <keyboard.h> +#include <emu.h> #include "dat.h" #include "fns.h" char *bindir = "/sys/lib/c64"; -Image *tmp, *bg, *red; -Rectangle picr, progr; -Mousectl *mc; -QLock pauselock; -int paused, scale; +Image *red; +Rectangle progr; u8int *rom; int nrom; -u64int keys; u16int joys; uchar *tape, tapever, tapeplay; ulong tapelen; @@ -26,7 +23,8 @@ progress(int a, int b) { static int cur; int w; - + + extern Image *bg; if(b == 0 || a == 0){ if(cur != 0){ draw(screen, progr, bg, nil, ZP); @@ -212,21 +210,6 @@ keyproc(void *) } static void -screeninit(void) -{ - Point p, q; - - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(picw/2*scale, pich/2*scale)), addpt(p, Pt(picw/2*scale, pich/2*scale))}; - p.y += pich*scale*3/4; - q = Pt(Dx(screen->r) * 2/5, 8); - progr = (Rectangle){subpt(p, q), addpt(p, q)}; - freeimage(tmp); - tmp = allocimage(display, Rect(0, 0, picw*scale, scale > 1 ? 1 : pich), XRGB32, 1, 0); - draw(screen, screen->r, bg, nil, ZP); -} - -static void usage(void) { fprint(2, "usage: %s [ -23a ] [ rom ]\n", argv0); @@ -236,17 +219,9 @@ usage(void) void threadmain(int argc, char **argv) { - scale = 1; - memreset(); ARGBEGIN { - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; case 'c': loadcart(EARGF(usage())); break; @@ -272,16 +247,8 @@ threadmain(int argc, char **argv) loadsys("crom.bin", crom, 4096); vicreset(); - - if(initdraw(nil, nil, nil) < 0) - sysfatal("initdraw: %r"); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); + initemu(picw, pich, 4, XRGB32, 1, keyproc); red = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xFF0000FF); - screeninit(); - proccreate(keyproc, nil, mainstacksize); nmien = IRQRESTORE; pc = memread(0xFFFC) | memread(0xFFFD) << 8; @@ -309,7 +276,8 @@ menu(void) static Menu m = { items, nil, 0 }; - + + extern Mousectl *mc; switch(menuhit(3, mc, &m, nil)){ case JOY: joymode = (joymode + 1) % 3; @@ -332,52 +300,11 @@ menu(void) void flush(void) { - extern u8int pic[]; -// vlong new, diff; -// static vlong old, delta; - - if(nbrecvul(mc->resizec) > 0){ - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - } + extern Mousectl *mc; + flushmouse(0); while(nbrecv(mc->c, &mc->Mouse) > 0) if((mc->buttons & 4) != 0) menu(); - if(scale == 1){ - loadimage(tmp, tmp->r, pic, picw*pich*4); - draw(screen, picr, tmp, nil, ZP); - }else{ - Rectangle r; - uchar *s; - int w; - - s = pic; - r = picr; - w = picw*4*scale; - while(r.min.y < picr.max.y){ - loadimage(tmp, tmp->r, s, w); - s += w; - r.max.y = r.min.y+scale; - draw(screen, r, tmp, nil, ZP); - r.min.y = r.max.y; - } - } - flushimage(display, 1); -/* - if(audioout() < 0){ - new = nsec(); - diff = 0; - if(old != 0){ - diff = BILLION/60 - (new - old) - delta; - if(diff >= MILLION) - sleep(diff/MILLION); - } - old = nsec(); - if(diff != 0){ - diff = (old - new) - (diff / MILLION) * MILLION; - delta += (diff - delta) / 100; - } - } -*/ + flushscreen(); + flushaudio(nil); } diff --git a/sys/src/games/c64/cpu.c b/sys/src/games/c64/cpu.c index 5f77ff92f..cafd8e333 100644 --- a/sys/src/games/c64/cpu.c +++ b/sys/src/games/c64/cpu.c @@ -1,5 +1,6 @@ #include <u.h> #include <libc.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -289,8 +290,6 @@ interrupt(int nmi, int brk) rP |= FLAGI; } -int trace; - void step(void) { diff --git a/sys/src/games/c64/dat.h b/sys/src/games/c64/dat.h index f8f1de1ce..723053d75 100644 --- a/sys/src/games/c64/dat.h +++ b/sys/src/games/c64/dat.h @@ -1,10 +1,8 @@ -typedef char s8int; - extern u8int reg[47], crom[4096], krom[8192], brom[8192], cram[1024], cart[16384]; extern u16int pc, curpc; extern u8int rP; -extern int nrdy, irq, nmi, irqen, nmien, trace; +extern int nrdy, irq, nmi, irqen, nmien; extern u8int pla; @@ -12,9 +10,8 @@ extern uchar *tape, tapever, tapeplay; extern ulong tapelen; extern u16int ppux, ppuy, picw, pich; -extern u64int keys; extern u16int joys; -extern int scale, region; +extern int region; enum { FLAGC = 1<<0, @@ -81,8 +78,6 @@ enum { }; enum { - BILLION = 1000*1000*1000, - MILLION = 1000*1000, HZ = 3579545, RATE = 44100, SAMPDIV = HZ / 3 / RATE, diff --git a/sys/src/games/c64/mem.c b/sys/src/games/c64/mem.c index 5245a55e9..8e00bec4b 100644 --- a/sys/src/games/c64/mem.c +++ b/sys/src/games/c64/mem.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/c64/vic.c b/sys/src/games/c64/vic.c index 8233f38c8..c181b2446 100644 --- a/sys/src/games/c64/vic.c +++ b/sys/src/games/c64/vic.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -9,7 +10,6 @@ u16int ppux, ppuy, lastx, wrapx, maxy, lvis, rvis, uvis, dvis, picw, pich, lbord u16int vc, vcbase, vmli; u8int badln, rc, displ, fract, visreg, hbord, vbord, rbord0, lbord0; u16int chrp[40]; -u8int pic[420*263*4*3]; u64int pxs, npxs, npxs0, opxs; u8int fg; @@ -92,24 +92,40 @@ vicreset(void) void pixeldraw(u64int p, int n) { - int i, j; + int i; + union { u8int c[4]; u32int l; } u; static u8int cr[] = {0, 255, 136, 170, 204, 0, 0, 238, 221, 102, 255, 51, 119, 170, 0, 187}; static u8int cg[] = {0, 255, 0, 255, 68, 204, 0, 238, 136, 68, 119, 51, 119, 255, 136, 187}; static u8int cb[] = {0, 255, 0, 238, 204, 85, 170, 119, 85, 0, 119, 51, 119, 102, 255, 187}; - u8int *q, c; - - q = pic + picidx * 4 * scale; + u8int c; + u32int *q; + + q = (u32int *)pic + picidx * scale; for(i = 0; i < n; i++){ c = p >> 56; p <<= 8; - - j = scale; - do{ - *q++ = cb[c]; - *q++ = cg[c]; - *q++ = cr[c]; - q++; - }while(--j); + u.c[0] = cb[c]; + u.c[1] = cg[c]; + u.c[2] = cr[c]; + u.c[3] = 0; + switch(scale){ + case 16: *q++ = u.l; + case 15: *q++ = u.l; + case 14: *q++ = u.l; + case 13: *q++ = u.l; + case 12: *q++ = u.l; + case 11: *q++ = u.l; + case 10: *q++ = u.l; + case 9: *q++ = u.l; + case 8: *q++ = u.l; + case 7: *q++ = u.l; + case 6: *q++ = u.l; + case 5: *q++ = u.l; + case 4: *q++ = u.l; + case 3: *q++ = u.l; + case 2: *q++ = u.l; + default: *q++ = u.l; + } } picidx += n; } diff --git a/sys/src/games/gb/apu.c b/sys/src/games/gb/apu.c index b01c2f80d..dc78992ac 100644 --- a/sys/src/games/gb/apu.c +++ b/sys/src/games/gb/apu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -475,7 +476,7 @@ audioout(void) if(sbufp == sbuf) return 0; cl = clock; - rc = write(fd, sbuf, (sbufp - sbuf) * 2); + rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2); if(rc > 0) sbufp -= (rc+1)/2; if(sbufp < sbuf) diff --git a/sys/src/games/gb/cpu.c b/sys/src/games/gb/cpu.c index 88900ea0b..81c45a034 100644 --- a/sys/src/games/gb/cpu.c +++ b/sys/src/games/gb/cpu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/gb/dat.h b/sys/src/games/gb/dat.h index 428cfffb9..68c03372c 100644 --- a/sys/src/games/gb/dat.h +++ b/sys/src/games/gb/dat.h @@ -1,10 +1,6 @@ -typedef char s8int; -typedef short s16int; -typedef long s32int; typedef struct Event Event; typedef struct MBC3Timer MBC3Timer; -extern int trace; extern u16int curpc; extern uchar *rom, *back, reg[256], oam[256]; @@ -24,7 +20,6 @@ extern u8int apustatus; extern u8int mode; extern u8int mbc, feat; -extern int keys, scale; enum { JOYP = 0x00, @@ -129,8 +124,6 @@ enum { TIMERSIZ = 18, PICW = 160, PICH = 144, - MILLION = 1000000, - BILLION = 1000000000, FREQ = 1<<23 }; diff --git a/sys/src/games/gb/gb.c b/sys/src/games/gb/gb.c index 374af931a..55ced730a 100644 --- a/sys/src/games/gb/gb.c +++ b/sys/src/games/gb/gb.c @@ -2,34 +2,28 @@ #include <libc.h> #include <thread.h> #include <draw.h> -#include <mouse.h> #include <keyboard.h> +#include <emu.h> #include "dat.h" #include "fns.h" int cpuhalt; -int scale, profile; -Rectangle picr; -Image *bg, *tmp; -Mousectl *mc; -int keys, paused, framestep, backup; -QLock pauselock; +int backup; int savefd = -1, saveframes; ulong clock; -int savereq, loadreq; u8int mbc, feat, mode; extern MBC3Timer timer, timerl; -void * -emalloc(ulong sz) +extern double TAU; +void +tauup(void) { - void *v; - - v = malloc(sz); - if(v == nil) - sysfatal("malloc: %r"); - setmalloctag(v, getcallerpc(&sz)); - return v; + TAU += 5000; +} +void +taudn(void) +{ + TAU -= 5000; } void @@ -204,174 +198,14 @@ loadrom(char *file) } void -screeninit(void) -{ - Point p; - - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * PICW/2, scale * PICH/2)), addpt(p, Pt(scale * PICW/2, scale * PICH/2))}; - freeimage(tmp); - tmp = allocimage(display, Rect(0, 0, scale * PICW, scale > 1 ? 1 : scale * PICH), XRGB32, scale > 1, 0); - draw(screen, screen->r, bg, nil, ZP); -} - -void -keyproc(void *) -{ - int fd, n, k; - static char buf[256]; - char *s; - Rune r; - extern double TAU; - - fd = open("/dev/kbd", OREAD); - if(fd < 0) - sysfatal("open: %r"); - for(;;){ - if(buf[0] != 0){ - n = strlen(buf)+1; - memmove(buf, buf+n, sizeof(buf)-n); - } - if(buf[0] == 0){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0) - sysfatal("read /dev/kbd: %r"); - buf[n-1] = 0; - buf[n] = 0; - } - if(buf[0] == 'c'){ - if(utfrune(buf, KF|5)) - savereq = 1; - if(utfrune(buf, KF|6)) - loadreq = 1; - if(utfrune(buf, Kdel)){ - close(fd); - threadexitsall(nil); - } - if(utfrune(buf, 't')) - trace = !trace; - if(utfrune(buf, KF|9)) - TAU += 5000; - if(utfrune(buf, KF|10)) - TAU -= 5000; - } - if(buf[0] != 'k' && buf[0] != 'K') - continue; - s = buf + 1; - k = 0; - while(*s != 0){ - s += chartorune(&r, s); - switch(r){ - case Kdel: close(fd); threadexitsall(nil); - case 'z': k |= 1<<5; break; - case 'x': k |= 1<<4; break; - case Kshift: k |= 1<<6; break; - case 10: k |= 1<<7; break; - case Kup: k |= 1<<2; break; - case Kdown: k |= 1<<3; break; - case Kleft: k |= 1<<1; break; - case Kright: k |= 1<<0; break; - case Kesc: - if(paused) - qunlock(&pauselock); - else - qlock(&pauselock); - paused = !paused; - break; - case KF|1: - if(paused){ - qunlock(&pauselock); - paused=0; - } - framestep = !framestep; - break; - } - } - k &= ~(k << 1 & 0x0a | k >> 1 & 0x05); - keys = k; - } - -} - -void -timing(void) -{ - static int fcount; - static vlong old; - static char buf[32]; - vlong new; - - if(++fcount == 60) - fcount = 0; - else - return; - new = nsec(); - if(new != old) - sprint(buf, "%6.2f%%", 1e11 / (new - old)); - else - buf[0] = 0; - draw(screen, rectaddpt(Rect(10, 10, 200, 30), screen->r.min), bg, nil, ZP); - string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, display->defaultfont, buf); - old = nsec(); -} - -void flush(void) { extern uchar pic[]; - Mouse m; static vlong old, delta; - vlong new, diff; - - if(nbrecvul(mc->resizec) > 0){ - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - } - while(nbrecv(mc->c, &m) > 0) - ; - if(scale == 1){ - loadimage(tmp, tmp->r, pic, PICW*PICH*4); - draw(screen, picr, tmp, nil, ZP); - } else { - Rectangle r; - uchar *s; - int w; - s = pic; - r = picr; - w = PICW*4*scale; - while(r.min.y < picr.max.y){ - loadimage(tmp, tmp->r, s, w); - s += w; - r.max.y = r.min.y+scale; - draw(screen, r, tmp, nil, ZP); - r.min.y = r.max.y; - } - } - flushimage(display, 1); - if(profile) - timing(); - if(audioout() < 0){ - new = nsec(); - diff = 0; - if(old != 0){ - diff = BILLION/60 - (new - old) - delta; - if(diff >= MILLION) - sleep(diff/MILLION); - } - old = nsec(); - if(diff != 0){ - diff = (old - new) - (diff / MILLION) * MILLION; - delta += (diff - delta) / 100; - } - } - if(framestep){ - paused = 1; - qlock(&pauselock); - framestep = 0; - } - + flushmouse(1); + flushscreen(); + flushaudio(audioout); if(saveframes > 0 && --saveframes == 0) flushback(); if(savereq){ @@ -430,20 +264,10 @@ threadmain(int argc, char **argv) int t; colinit(); - scale = 1; ARGBEGIN { - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; case 'a': audioinit(); break; - case 'T': - profile++; - break; case 'c': mode |= CGB; break; @@ -460,15 +284,17 @@ threadmain(int argc, char **argv) usage(); loadrom(argv[0]); - - if(initdraw(nil, nil, nil) < 0) - sysfatal("initdraw: %r"); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - proccreate(keyproc, nil, mainstacksize); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - screeninit(); + initemu(PICW, PICH, 4, XRGB32, 1, nil); + regkey("b", 'z', 1<<5); + regkey("a", 'x', 1<<4); + regkey("control", Kshift, 1<<6); + regkey("start", '\n', 1<<7); + regkey("up", Kup, 1<<2); + regkey("down", Kdown, 1<<3); + regkey("left", Kleft, 1<<1); + regkey("right", Kright, 1<<0); + regkeyfn(KF|9, tauup); + regkeyfn(KF|10, taudn); eventinit(); meminit(); diff --git a/sys/src/games/gb/mem.c b/sys/src/games/gb/mem.c index a9c629a13..a6c6c7599 100644 --- a/sys/src/games/gb/mem.c +++ b/sys/src/games/gb/mem.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/gb/ppu.c b/sys/src/games/gb/ppu.c index bd1ecf905..389581621 100644 --- a/sys/src/games/gb/ppu.c +++ b/sys/src/games/gb/ppu.c @@ -1,11 +1,11 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" u8int ppustate, ppuy; -u32int pic[PICW*PICH*3]; ulong hblclock, rendclock; jmp_buf mainjmp, renderjmp; static int cyc, done, ppux, ppux0; @@ -63,7 +63,7 @@ ppurender(void) } ppux = 0; ppux0 = 0; - picp = pic + ppuy * PICW * scale; + picp = (u32int*)pic + ppuy * PICW * scale; y = ppuy + reg[SCY] << 1 & 14; ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | reg[SCX] >> 3; x = -(reg[SCX] & 7); @@ -197,7 +197,7 @@ sprites(void) int x, x1; u16int chr; - picp = pic + ppuy * PICW * scale; + picp = (u32int*)pic + ppuy * PICW * scale; for(q = spr; q < sprm; q++){ if(q->x <= ppux0 || q->x >= ppux + 8) continue; @@ -254,18 +254,31 @@ static void lineexpand(void) { u32int *picp, *p, *q, l; - int i, s; + int i; - s = scale; - picp = pic + ppuy * PICW * s; + picp = (u32int*)pic + ppuy * PICW * scale; p = picp + PICW; q = picp + PICW * scale; for(i = PICW; --i >= 0; ){ l = *--p; - *--q = l; - *--q = l; - if(scale == 3) - *--q = l; + switch(scale){ + case 16: *--q = l; + case 15: *--q = l; + case 14: *--q = l; + case 13: *--q = l; + case 12: *--q = l; + case 11: *--q = l; + case 10: *--q = l; + case 9: *--q = l; + case 8: *--q = l; + case 7: *--q = l; + case 6: *--q = l; + case 5: *--q = l; + case 4: *--q = l; + case 3: *--q = l; + case 2: *--q = l; + case 1: *--q = l; + } } } diff --git a/sys/src/games/gba/apu.c b/sys/src/games/gba/apu.c index 3e8883572..4858aced9 100644 --- a/sys/src/games/gba/apu.c +++ b/sys/src/games/gba/apu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -350,7 +351,7 @@ sndwrite(u16int a, u16int v) void audioinit(void) { - fd = open("/dev/audio", OWRITE); + fd = open("/dev/audio", OWRITE); if(fd < 0) sysfatal("open: %r"); sbufp = sbuf; @@ -370,7 +371,7 @@ audioout(void) if(sbufp == sbuf) return 0; cl = clock; - rc = write(fd, sbuf, (sbufp - sbuf) * 2); + rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2); if(rc > 0) sbufp -= (rc+1)/2; if(sbufp < sbuf) diff --git a/sys/src/games/gba/cpu.c b/sys/src/games/gba/cpu.c index c92e4ff9d..a8354324f 100644 --- a/sys/src/games/gba/cpu.c +++ b/sys/src/games/gba/cpu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -34,7 +35,7 @@ u32int curpc; int irq; u32int instr0, instr1, pipel = -1; -int cyc, trace; +int cyc; Var cpuvars[] = { ARR(r), VAR(cpsr), VAR(spsr), ARR(saver), VAR(irq), diff --git a/sys/src/games/gba/dat.h b/sys/src/games/gba/dat.h index a609b850b..d930c7b28 100644 --- a/sys/src/games/gba/dat.h +++ b/sys/src/games/gba/dat.h @@ -1,9 +1,4 @@ -typedef char s8int; -typedef short s16int; -typedef long s32int; -typedef vlong s64int; - -extern int cpuhalt, trace, keys; +extern int cpuhalt; extern u32int curpc; extern int irq; @@ -18,7 +13,6 @@ extern int nrom, nback, backup; extern int hblank, ppuy; extern int clock; -extern int scale; typedef struct Event Event; struct Event { @@ -141,8 +135,6 @@ enum { KB = 1024, BACKTYPELEN = 64, HZ = 16777216, - MILLION = 1000000, - BILLION = 1000000000, }; typedef struct Var Var; diff --git a/sys/src/games/gba/gba.c b/sys/src/games/gba/gba.c index 5a53b68b3..06e90b998 100644 --- a/sys/src/games/gba/gba.c +++ b/sys/src/games/gba/gba.c @@ -2,36 +2,19 @@ #include <libc.h> #include <thread.h> #include <draw.h> -#include <mouse.h> #include <keyboard.h> +#include <emu.h> #include "dat.h" #include "fns.h" int cpuhalt; -int scale, profile; -Rectangle picr; -Image *bg, *tmp; -Mousectl *mc; -int keys, paused, framestep, backup; -QLock pauselock; +Image *tmp; +int backup; int savefd, saveframes; int clock; -int savereq, loadreq; char *biosfile = "/sys/games/lib/gbabios.bin"; -void * -emalloc(ulong sz) -{ - void *v; - - v = malloc(sz); - if(v == nil) - sysfatal("malloc: %r"); - setmalloctag(v, getcallerpc(&sz)); - return v; -} - void writeback(void) { @@ -212,172 +195,14 @@ loadrom(char *file) } void -screeninit(void) -{ - Point p; - - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * 120, scale * 80)), addpt(p, Pt(scale * 120, scale * 80))}; - freeimage(tmp); - 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); - draw(screen, screen->r, bg, nil, ZP); -} - -void -keyproc(void *) -{ - int fd, n, k; - static char buf[256]; - char *s; - Rune r; - - fd = open("/dev/kbd", OREAD); - if(fd < 0) - sysfatal("open: %r"); - for(;;){ - if(buf[0] != 0){ - n = strlen(buf)+1; - memmove(buf, buf+n, sizeof(buf)-n); - } - if(buf[0] == 0){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0) - sysfatal("read /dev/kbd: %r"); - buf[n-1] = 0; - buf[n] = 0; - } - if(buf[0] == 'c'){ - if(utfrune(buf, KF|5)) - savereq = 1; - if(utfrune(buf, KF|6)) - loadreq = 1; - if(utfrune(buf, Kdel)){ - close(fd); - threadexitsall(nil); - } - if(utfrune(buf, 't')) - trace = !trace; - } - if(buf[0] != 'k' && buf[0] != 'K') - continue; - s = buf + 1; - k = 0; - while(*s != 0){ - s += chartorune(&r, s); - switch(r){ - case Kdel: close(fd); threadexitsall(nil); - case 'z': k |= 1<<1; break; - case 'x': k |= 1<<0; break; - case 'a': k |= 1<<9; break; - case 's': k |= 1<<8; break; - case Kshift: k |= 1<<2; break; - case 10: k |= 1<<3; break; - case Kup: k |= 1<<6; break; - case Kdown: k |= 1<<7; break; - case Kleft: k |= 1<<5; break; - case Kright: k |= 1<<4; break; - case Kesc: - if(paused) - qunlock(&pauselock); - else - qlock(&pauselock); - paused = !paused; - break; - case KF|1: - if(paused){ - qunlock(&pauselock); - paused=0; - } - framestep = !framestep; - break; - } - } - k &= ~(k << 1 & 0xa0 | k >> 1 & 0x50); - keys = k; - } - -} - -void -timing(void) -{ - static int fcount; - static vlong old; - static char buf[32]; - vlong new; - - if(++fcount == 60) - fcount = 0; - else - return; - new = nsec(); - if(new != old) - sprint(buf, "%6.2f%%", 1e11 / (new - old)); - else - buf[0] = 0; - draw(screen, rectaddpt(Rect(10, 10, 200, 30), screen->r.min), bg, nil, ZP); - string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, display->defaultfont, buf); - old = nsec(); -} - -void flush(void) { - extern uchar pic[]; - Mouse m; int x; - static vlong old, delta; - vlong new, diff; - if(nbrecvul(mc->resizec) > 0){ - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - } - while(nbrecv(mc->c, &m) > 0) - ; - if(scale == 1){ - loadimage(tmp, tmp->r, pic, 240*160*2); - draw(screen, picr, tmp, nil, ZP); - } else { - Rectangle r; - uchar *s; - int w; + flushmouse(1); + flushscreen(); + flushaudio(audioout); - s = pic; - r = picr; - w = 240*2*scale; - while(r.min.y < picr.max.y){ - loadimage(tmp, tmp->r, s, w); - s += w; - r.max.y = r.min.y+scale; - draw(screen, r, tmp, nil, ZP); - r.min.y = r.max.y; - } - } - flushimage(display, 1); - if(profile) - timing(); - if(audioout() < 0){ - new = nsec(); - diff = 0; - if(old != 0){ - diff = BILLION/60 - (new - old) - delta; - if(diff >= MILLION) - sleep(diff/MILLION); - } - old = nsec(); - if(diff != 0){ - diff = (old - new) - (diff / MILLION) * MILLION; - delta += (diff - delta) / 100; - } - } - if(framestep){ - paused = 1; - qlock(&pauselock); - framestep = 0; - } - if(saveframes > 0 && --saveframes == 0) flushback(); @@ -395,7 +220,7 @@ flush(void) void usage(void) { - fprint(2, "usage: %s [-23aT] [-s savetype] [-b biosfile] rom\n", argv0); + fprint(2, "usage: %s [-aT] [-s savetype] [-b biosfile] rom\n", argv0); exits("usage"); } @@ -405,14 +230,7 @@ threadmain(int argc, char **argv) char *s; int t; - scale = 1; ARGBEGIN { - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; case 'a': audioinit(); break; @@ -425,9 +243,6 @@ threadmain(int argc, char **argv) case 'b': biosfile = strdup(EARGF(usage())); break; - case 'T': - profile++; - break; default: usage(); } ARGEND; @@ -436,16 +251,17 @@ threadmain(int argc, char **argv) loadbios(); loadrom(argv[0]); - - if(initdraw(nil, nil, nil) < 0) - sysfatal("initdraw: %r"); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - proccreate(keyproc, nil, mainstacksize); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - screeninit(); - + initemu(240, 160, 2, CHAN4(CIgnore, 1, CBlue, 5, CGreen, 5, CRed, 5), 1, nil); + regkey("b", 'z', 1<<1); + regkey("a", 'x', 1<<0); + regkey("l1", 'a', 1<<9); + regkey("r1", 's', 1<<8); + regkey("control", Kshift, 1<<2); + regkey("start", '\n', 1<<3); + regkey("up", Kup, 1<<6); + regkey("down", Kdown, 1<<7); + regkey("left", Kleft, 1<<5); + regkey("right", Kright, 1<<4); eventinit(); memreset(); reset(); diff --git a/sys/src/games/gba/mem.c b/sys/src/games/gba/mem.c index 75ff9d31c..032f35eae 100644 --- a/sys/src/games/gba/mem.c +++ b/sys/src/games/gba/mem.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/gba/ppu.c b/sys/src/games/gba/ppu.c index a87caba17..7de5a1e7b 100644 --- a/sys/src/games/gba/ppu.c +++ b/sys/src/games/gba/ppu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -11,7 +12,6 @@ int ppux0; u32int pixcol[480]; u8int pixpri[480]; u8int pixwin[240]; -uchar pic[240*160*3*2]; int objalpha; typedef struct bg bg; @@ -643,40 +643,6 @@ colormath(int x1) } void -linecopy(void) -{ - u32int *p; - uchar *q; - u16int *r; - u16int v; - union { u16int w; u8int b[2]; } u; - int n; - - p = pixcol; - q = pic + ppuy * 240 * 2 * scale; - r = (u16int*)q; - n = 240; - while(n--){ - v = *p++; - if(scale == 1){ - *q++ = v; - *q++ = v >> 8; - continue; - } - u.b[0] = v; - u.b[1] = v >> 8; - if(scale == 2){ - *r++ = u.w; - *r++ = u.w; - }else{ - *r++ = u.w; - *r++ = u.w; - *r++ = u.w; - } - } -} - -void syncppu(int x1) { int i; @@ -725,6 +691,43 @@ syncppu(int x1) } void +linecopy(u32int *p, int y) +{ + uchar *q; + u16int *r; + u16int v; + union { u16int w; u8int b[2]; } u; + int n; + + q = pic + y * 240 * 2 * scale; + r = (u16int*)q; + n = 240; + while(n--){ + v = *p++; + u.b[0] = v; + u.b[1] = v >> 8; + switch(scale){ + case 16: *r++ = u.w; + case 15: *r++ = u.w; + case 14: *r++ = u.w; + case 13: *r++ = u.w; + case 12: *r++ = u.w; + case 11: *r++ = u.w; + case 10: *r++ = u.w; + case 9: *r++ = u.w; + case 8: *r++ = u.w; + case 7: *r++ = u.w; + case 6: *r++ = u.w; + case 5: *r++ = u.w; + case 4: *r++ = u.w; + case 3: *r++ = u.w; + case 2: *r++ = u.w; + default: *r++ = u.w; + } + } +} + +void hblanktick(void *) { extern Event evhblank; @@ -755,7 +758,7 @@ hblanktick(void *) }else{ syncppu(240); if(ppuy < 160) - linecopy(); + linecopy(pixcol, ppuy); addevent(&evhblank, 68*4); hblank = 1; if((stat & IRQHBLEN) != 0) diff --git a/sys/src/games/md/cpu.c b/sys/src/games/md/cpu.c index 8a7e8db86..1a0325f52 100644 --- a/sys/src/games/md/cpu.c +++ b/sys/src/games/md/cpu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -19,7 +20,7 @@ extern u32int irql[8]; u32int irqla[8]; u16int rS; static u32int op; -int trace, tim; +int tim; #define ra (r+8) static void diff --git a/sys/src/games/md/dat.h b/sys/src/games/md/dat.h index f61e9a13e..5323a7d79 100644 --- a/sys/src/games/md/dat.h +++ b/sys/src/games/md/dat.h @@ -1,9 +1,4 @@ -typedef signed char s8int; -typedef signed short s16int; -typedef signed long s32int; - extern u32int curpc, irq; -extern int trace, debug; extern u8int reg[32]; extern u8int dma; @@ -18,8 +13,6 @@ extern u8int *sram; extern u32int sramctl, sram0, sram1; extern int savefd, saveclock; -extern int keys, scale; - extern u16int vram[32768], vsram[40]; extern u32int cramc[64]; extern u16int vdpstat; @@ -82,8 +75,6 @@ enum { RATE = 44100, SAMPDIV = FREQ / RATE, SAVEFREQ = FREQ / 4, - MILLION = 1000 * 1000, - BILLION = 1000 * 1000 * 1000, }; enum { diff --git a/sys/src/games/md/md.c b/sys/src/games/md/md.c index f8ffcc52c..557668dc7 100644 --- a/sys/src/games/md/md.c +++ b/sys/src/games/md/md.c @@ -3,29 +3,18 @@ #include <thread.h> #include <draw.h> #include <keyboard.h> -#include <mouse.h> +#include <emu.h> #include "dat.h" #include "fns.h" -int debug; - u16int *prg; int nprg; u8int *sram; u32int sramctl, nsram, sram0, sram1; int savefd = -1; -int keys; - int dmaclock, vdpclock, z80clock, audioclock, ymclock, saveclock; -int scale, paused; -QLock pauselock; -Mousectl *mc; -Channel *flushc; -Rectangle picr; -Image *tmp, *bg; - void flushram(void) { @@ -114,146 +103,14 @@ loadrom(char *file) } void -screeninit(void) -{ - Point p; - - originwindow(screen, Pt(0, 0), screen->r.min); - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * 160, scale * 112)), addpt(p, Pt(scale * 160, scale * 112))}; - if(tmp != nil) freeimage(tmp); - tmp = allocimage(display, Rect(0, 0, scale * 320, scale > 1 ? 1 : scale * 224), XRGB32, scale > 1, 0); - if(bg != nil) freeimage(bg); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - draw(screen, screen->r, bg, nil, ZP); -} - -void -screenproc(void *) -{ - extern u8int pic[320*224*4*4]; - extern int intla; - Rectangle r; - uchar *s; - int w, h; - - enum { AMOUSE, ARESIZE, AFLUSH, AEND }; - Alt a[AEND+1] = { - { mc->c, nil, CHANRCV }, - { mc->resizec, nil, CHANRCV }, - { flushc, nil, CHANRCV }, - { nil, nil, CHANEND } - }; - - for(;;){ - switch(alt(a)){ - case ARESIZE: - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - /* wet floor */ - case AFLUSH: - if(scale == 1){ - loadimage(tmp, tmp->r, pic, 320*224*4); - draw(screen, picr, tmp, nil, ZP); - }else{ - s = pic; - r = picr; - w = 320*4*scale; - h = scale; - if(intla && (h & 1) == 0) - h >>= 1; - while(r.min.y < picr.max.y){ - loadimage(tmp, tmp->r, s, w); - s += w; - r.max.y = r.min.y+h; - draw(screen, r, tmp, nil, ZP); - r.min.y = r.max.y; - } - } - flushimage(display, 1); - break; - } - } -} - -void -keyproc(void *) -{ - int fd, n, k; - static char buf[256]; - char *s; - Rune r; - - fd = open("/dev/kbd", OREAD); - if(fd < 0) - sysfatal("open: %r"); - for(;;){ - if(buf[0] != 0){ - n = strlen(buf)+1; - memmove(buf, buf+n, sizeof(buf)-n); - } - if(buf[0] == 0){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0) - sysfatal("read /dev/kbd: %r"); - buf[n-1] = 0; - buf[n] = 0; - } - if(buf[0] == 'c'){ - if(utfrune(buf, Kdel)){ - close(fd); - threadexitsall(nil); - } - if(utfrune(buf, 't')) - trace = !trace; - } - if(buf[0] != 'k' && buf[0] != 'K') - continue; - s = buf + 1; - k = 0xc00; - while(*s != 0){ - s += chartorune(&r, s); - if(r >= '0' && r <= '9') debug = r - '0'; - switch(r){ - case Kdel: close(fd); threadexitsall(nil); - case 'c': k |= 0x0020; break; - case 'x': k |= 0x0010; break; - case 'z': k |= 0x1000; break; - case 10: k |= 0x2000; break; - case Kup: k |= 0x0101; break; - case Kdown: k |= 0x0202; break; - case Kleft: k |= 0x0004; break; - case Kright: k |= 0x0008; break; - case Kesc: - if(paused) - qunlock(&pauselock); - else - qlock(&pauselock); - paused = !paused; - break; - } - } - keys = ~k; - } -} - -void threadmain(int argc, char **argv) { int t; - scale = 1; ARGBEGIN{ case 'a': initaudio(); break; - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; default: ; } ARGEND; @@ -263,15 +120,15 @@ threadmain(int argc, char **argv) threadexitsall("usage"); } loadrom(*argv); - if(initdraw(nil, nil, argv0) < 0) - sysfatal("initdraw: %r"); - flushc = chancreate(sizeof(ulong), 1); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - screeninit(); - proccreate(keyproc, nil, 8192); - proccreate(screenproc, nil, 8192); + initemu(320, 224, 4, XRGB32, 1, nil); + regkey("a", 'c', 1<<5); + regkey("b", 'x', 1<<4); + regkey("y", 'z', 1<<12); + regkey("start", '\n', 1<<13); + regkey("up", Kup, 0x101); + regkey("down", Kdown, 0x202); + regkey("left", Kleft, 1<<2); + regkey("right", Kright, 1<<3); cpureset(); vdpmode(); ymreset(); @@ -320,22 +177,7 @@ threadmain(int argc, char **argv) void flush(void) { - static vlong old, delta; - vlong new, diff; - - sendul(flushc, 1); /* flush screen */ - if(audioout() < 0){ - new = nsec(); - diff = 0; - if(old != 0){ - diff = BILLION/60 - (new - old) - delta; - if(diff >= MILLION) - sleep(diff/MILLION); - } - old = nsec(); - if(diff != 0){ - diff = (old - new) - (diff / MILLION) * MILLION; - delta += (diff - delta) / 100; - } - } + flushmouse(1); + flushscreen(); + flushaudio(audioout); } diff --git a/sys/src/games/md/mem.c b/sys/src/games/md/mem.c index f3b6ede8f..083abaa29 100644 --- a/sys/src/games/md/mem.c +++ b/sys/src/games/md/mem.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -31,7 +32,7 @@ regread(u16int a) switch(a | 1){ case 0x0001: return 0xa0; case 0x0003: - v = keys; + v = ~(keys & 0xffff); if((ctl[0] & 0x40) == 0) v >>= 8; return ctl[0] & 0xc0 | v & 0x3f; diff --git a/sys/src/games/md/vdp.c b/sys/src/games/md/vdp.c index e87306559..51d5f20a1 100644 --- a/sys/src/games/md/vdp.c +++ b/sys/src/games/md/vdp.c @@ -1,10 +1,10 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" -u8int pic[320*224*4*4]; u16int vdpstat = 0x3400; int vdpx, vdpy, vdpyy, frame, intla; u16int hctr; @@ -29,32 +29,31 @@ vdpmode(void) static void pixeldraw(int x, int y, int v) { - u8int *p; - u32int *q; - union { u32int w; u8int b[4]; } u; + u32int *p; + union { u32int l; u8int b[4]; } u; - if(scale == 1){ - p = pic + (x + y * 320) * 4; - p[0] = v >> 16; - p[1] = v >> 8; - p[2] = v; - return; - } + p = (u32int *)pic + (x + y * 320) * scale; u.b[0] = v >> 16; u.b[1] = v >> 8; u.b[2] = v; u.b[3] = 0; - if(scale == 2){ - if(intla) - y = y << 1 | frame; - q = (u32int*)pic + (x + y * 320) * 2; - q[0] = u.w; - q[1] = u.w; - }else{ - q = (u32int*)pic + (x + y * 320) * 3; - q[0] = u.w; - q[1] = u.w; - q[2] = u.w; + switch(scale){ + case 16: *p++ = u.l; + case 15: *p++ = u.l; + case 14: *p++ = u.l; + case 13: *p++ = u.l; + case 12: *p++ = u.l; + case 11: *p++ = u.l; + case 10: *p++ = u.l; + case 9: *p++ = u.l; + case 8: *p++ = u.l; + case 7: *p++ = u.l; + case 6: *p++ = u.l; + case 5: *p++ = u.l; + case 4: *p++ = u.l; + case 3: *p++ = u.l; + case 2: *p++ = u.l; /* intla ignored */ + default: *p = u.l; } } diff --git a/sys/src/games/md/ym.c b/sys/src/games/md/ym.c index 2bd83af0a..ca3988433 100644 --- a/sys/src/games/md/ym.c +++ b/sys/src/games/md/ym.c @@ -1,11 +1,10 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" -extern int debug; - u8int ym[512]; enum { MODE = 0x27, @@ -436,7 +435,7 @@ audioout(void) return -1; if(sbufp == sbuf) return 0; - rc = write(fd, sbuf, (sbufp - sbuf) * 2); + rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2); if(rc > 0) sbufp -= (rc+1)/2; if(sbufp < sbuf) diff --git a/sys/src/games/nes/apu.c b/sys/src/games/nes/apu.c index cd0a642b2..52e8e36b5 100644 --- a/sys/src/games/nes/apu.c +++ b/sys/src/games/nes/apu.c @@ -2,6 +2,7 @@ #include <libc.h> #include <thread.h> #include <draw.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -279,7 +280,7 @@ audioout(void) return -1; if(sbufp == sbuf) return 0; - rc = write(fd, sbuf, (sbufp - sbuf) * 2); + rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2); if(rc > 0) sbufp -= (rc+1)/2; if(sbufp < sbuf) diff --git a/sys/src/games/nes/dat.h b/sys/src/games/nes/dat.h index 8da07fa84..4162f0904 100644 --- a/sys/src/games/nes/dat.h +++ b/sys/src/games/nes/dat.h @@ -6,14 +6,14 @@ extern u16int pput, ppuv; extern u8int ppusx, vrambuf; extern int mirr, ppux, ppuy, odd, vramlatch, keylatch, keylatch2; -extern int map, scale, mmc3hack, oflag; +extern int map, mmc3hack, oflag; extern uchar *prg, *chr; extern int nprg, nchr, map, chrram; extern u8int apuseq, apuctr[13]; extern u16int dmcaddr, dmccnt; -extern int keys, keys2, clock, ppuclock, apuclock, dmcclock, dmcfreq, saveclock, paused; +extern int clock, ppuclock, apuclock, dmcclock, dmcfreq, saveclock; extern void (*mapper[])(int, u8int); @@ -78,8 +78,6 @@ enum { enum { FREQ = 21477272, - MILLION = 1000000, - BILLION = 1000000000, APUDIV = 89490, RATE = 44100, SAMPDIV = FREQ / RATE, diff --git a/sys/src/games/nes/mem.c b/sys/src/games/nes/mem.c index 575cf0c0e..52e3162ba 100644 --- a/sys/src/games/nes/mem.c +++ b/sys/src/games/nes/mem.c @@ -2,6 +2,7 @@ #include <libc.h> #include <thread.h> #include <draw.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/nes/nes.c b/sys/src/games/nes/nes.c index aa9c4fa2a..2b4988aec 100644 --- a/sys/src/games/nes/nes.c +++ b/sys/src/games/nes/nes.c @@ -2,22 +2,17 @@ #include <libc.h> #include <draw.h> #include <thread.h> -#include <mouse.h> #include <keyboard.h> +#include <emu.h> #include "dat.h" #include "fns.h" extern uchar ppuram[16384]; int nprg, nchr, map, chrram; uchar *prg, *chr; -int scale; -Rectangle picr; -Image *tmp, *bg; int clock, ppuclock, apuclock, dmcclock, dmcfreq, sampclock, msgclock, saveclock; -Mousectl *mc; -int keys, keys2, paused, savereq, loadreq, oflag, savefd = -1; +int oflag, savefd = -1; int mirr; -QLock pauselock; void message(char *fmt, ...) @@ -122,139 +117,18 @@ loadrom(char *file, int sflag) mapper[map](INIT, 0); } -extern int trace; - -void -joyproc(void *) -{ - char *s, *down[9]; - static char buf[64]; - int n, k, j; - - j = 1; - for(;;){ - n = read(0, buf, sizeof(buf) - 1); - if(n <= 0) - sysfatal("read: %r"); - buf[n] = 0; - n = getfields(buf, down, nelem(down), 1, " "); - k = 0; - for(n--; n >= 0; n--){ - s = down[n]; - if(strcmp(s, "joy1") == 0) - j = 1; - else if(strcmp(s, "joy2") == 0) - j = 2; - else if(strcmp(s, "a") == 0) - k |= 1<<0; - else if(strcmp(s, "b") == 0) - k |= 1<<1; - else if(strcmp(s, "control") == 0) - k |= 1<<2; - else if(strcmp(s, "start") == 0) - k |= 1<<3; - else if(strcmp(s, "up") == 0) - k |= 1<<4; - else if(strcmp(s, "down") == 0) - k |= 1<<5; - else if(strcmp(s, "left") == 0) - k |= 1<<6; - else if(strcmp(s, "right") == 0) - k |= 1<<7; - } - if(j == 2) - keys2 = k; - else - keys = k; - } -} - -void -keyproc(void *) -{ - int fd, n, k; - static char buf[256]; - char *s; - Rune r; - - fd = open("/dev/kbd", OREAD); - if(fd < 0) - sysfatal("open: %r"); - for(;;){ - if(buf[0] != 0){ - n = strlen(buf)+1; - memmove(buf, buf+n, sizeof(buf)-n); - } - if(buf[0] == 0){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0) - sysfatal("read /dev/kbd: %r"); - buf[n-1] = 0; - buf[n] = 0; - } - if(buf[0] == 'c'){ - if(utfrune(buf, Kdel)){ - close(fd); - threadexitsall(nil); - } - if(utfrune(buf, KF|5)) - savereq = 1; - if(utfrune(buf, KF|6)) - loadreq = 1; - if(utfrune(buf, 't')) - trace ^= 1; - } - if(buf[0] != 'k' && buf[0] != 'K') - continue; - s = buf + 1; - k = 0; - while(*s != 0){ - s += chartorune(&r, s); - switch(r){ - case Kdel: close(fd); threadexitsall(nil); - case 'x': k |= 1<<0; break; - case 'z': k |= 1<<1; break; - case Kshift: k |= 1<<2; break; - case 10: k |= 1<<3; break; - case Kup: k |= 1<<4; break; - case Kdown: k |= 1<<5; break; - case Kleft: k |= 1<<6; break; - case Kright: k |= 1<<7; break; - case Kesc: - if(paused) - qunlock(&pauselock); - else - qlock(&pauselock); - paused = !paused; - break; - } - } - keys = k; - } -} - void threadmain(int argc, char **argv) { - int t, h, sflag; - Point p; + int t, sflag; - scale = 1; - h = 240; sflag = 0; ARGBEGIN { case 'a': initaudio(); break; - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; case 'o': oflag = 1; - h -= 16; break; case 's': sflag = 1; @@ -269,20 +143,16 @@ threadmain(int argc, char **argv) threadexitsall("usage"); } loadrom(argv[0], sflag); - if(initdraw(nil, nil, nil) < 0) - sysfatal("initdraw: %r"); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - proccreate(joyproc, nil, 8192); - proccreate(keyproc, nil, 8192); - originwindow(screen, Pt(0, 0), screen->r.min); - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * 128, scale * h/2)), addpt(p, Pt(scale * 128, scale * h/2))}; - tmp = allocimage(display, Rect(0, 0, scale * 256, scale * h), XRGB32, 0, 0); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - draw(screen, screen->r, bg, nil, ZP); - + initemu(256, 240 - oflag * 16, 4, XRGB32, 1, nil); + regkey("b", 'z', 1<<1); + regkey("a", 'x', 1<<0); + regkey("control", Kshift, 1<<2); + regkey("start", '\n', 1<<3); + regkey("up", Kup, 1<<4); + regkey("down", Kdown, 1<<5); + regkey("left", Kleft, 1<<6); + regkey("right", Kright, 1<<7); + pc = memread(0xFFFC) | memread(0xFFFD) << 8; rP = FLAGI; dmcfreq = 12 * 428; @@ -324,7 +194,8 @@ threadmain(int argc, char **argv) if(msgclock > 0){ msgclock -= t; if(msgclock <= 0){ - draw(screen, screen->r, bg, nil, ZP); + extern Image *bg; + draw(screen, screen->r, bg, nil, ZP); msgclock = 0; } } diff --git a/sys/src/games/nes/ppu.c b/sys/src/games/nes/ppu.c index 5c1756a19..498c20082 100644 --- a/sys/src/games/nes/ppu.c +++ b/sys/src/games/nes/ppu.c @@ -3,18 +3,17 @@ #include <thread.h> #include <draw.h> #include <mouse.h> +#include <emu.h> #include "dat.h" #include "fns.h" int ppuy, ppux, odd; -uchar pic[256*240*4*9]; static void pixel(int x, int y, int val, int back) { - int Y; union { u8int c[4]; u32int l; } u; - u32int *p, l; + u32int *p; static u8int palred[64] = { 0x7C, 0x00, 0x00, 0x44, 0x94, 0xA8, 0xA8, 0x88, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -50,32 +49,31 @@ pixel(int x, int y, int val, int back) u.c[1] = palgreen[val]; u.c[2] = palred[val]; u.c[3] = back ? 0 : 0xFF; - l = u.l; - if(scale == 3){ - p = ((u32int*)pic) + y * 3 * 3 * 256 + 3 * x; - for(Y = 0; Y < 3; Y++){ - *p++ = l; - *p++ = l; - *p = l; - p += 3 * 256 - 2; - } - }else if(scale == 2){ - p = ((u32int*)pic) + y * 2 * 2 * 256 + 2 * x; - *p++ = l; - *p = l; - p += 2 * 256 - 1; - *p++ = l; - *p = l; - }else{ - p = ((u32int*)pic) + y * 256 + x; - *p = l; + p = (u32int *)pic + y * 256 * scale + x * scale; + switch(scale){ + case 16: *p++ = u.l; + case 15: *p++ = u.l; + case 14: *p++ = u.l; + case 13: *p++ = u.l; + case 12: *p++ = u.l; + case 11: *p++ = u.l; + case 10: *p++ = u.l; + case 9: *p++ = u.l; + case 8: *p++ = u.l; + case 7: *p++ = u.l; + case 6: *p++ = u.l; + case 5: *p++ = u.l; + case 4: *p++ = u.l; + case 3: *p++ = u.l; + case 2: *p++ = u.l; + default: *p = u.l; } } static int iscolor(int x, int y) { - return pic[y * scale * scale * 256 * 4 + x * scale * 4 + 3] != 0; + return pic[(scale * 4) * (y * 256 + x) + 3] != 0; } static int @@ -252,52 +250,9 @@ drawsprites(int show) static void flush(void) { - extern Rectangle picr; - extern Image *tmp, *bg; - extern Mousectl *mc; - static vlong old, delta; - vlong new, diff; - Mouse m; - Point p; - int h; - - h = 240; - if(oflag) - h -= 16; - while(nbrecv(mc->c, &m) > 0) - ; - if(nbrecvul(mc->resizec) > 0){ - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * 128, scale * h/2)), addpt(p, Pt(scale * 128, scale * h/2))}; - if(bg->chan != screen->chan){ - freeimage(bg); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - } - draw(screen, screen->r, bg, nil, ZP); - } - if(screen->chan != tmp->chan || !rectinrect(picr, screen->r)){ - loadimage(tmp, tmp->r, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale); - draw(screen, picr, tmp, nil, ZP); - }else - loadimage(screen, picr, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale); - flushimage(display, 1); - memset(pic, sizeof pic, 0); - if(audioout() < 0){ - new = nsec(); - diff = 0; - if(old != 0){ - diff = BILLION/60 - (new - old) - delta; - if(diff >= MILLION) - sleep(diff/MILLION); - } - old = nsec(); - if(diff != 0){ - diff = (old - new) - (diff / MILLION) * MILLION; - delta += (diff - delta) / 100; - } - } + flushmouse(1); + flushscreen(); + flushaudio(audioout); } void diff --git a/sys/src/games/snes/cpu.c b/sys/src/games/snes/cpu.c index 602d4ca8f..dbec220a4 100644 --- a/sys/src/games/snes/cpu.c +++ b/sys/src/games/snes/cpu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -640,8 +641,6 @@ cpureset(void) rP = 0x35; } -int trace; - int cpustep(void) { diff --git a/sys/src/games/snes/dat.h b/sys/src/games/snes/dat.h index 86a14a5a4..971ea724c 100644 --- a/sys/src/games/snes/dat.h +++ b/sys/src/games/snes/dat.h @@ -1,14 +1,10 @@ -typedef signed char s8int; -typedef signed short s16int; - extern u8int rP, dma, nmi, irq, emu, wai; extern u16int rA, rX, rY, rS, rD, pc; extern u32int rPB, rDB, curpc, hdma; -extern int trace; extern uchar *prg, *sram; extern int nprg, nsram, hirom; -extern u32int keys, keylatch, lastkeys; +extern u32int keylatch, lastkeys; extern u8int reg[32768], mem[131072], spcmem[65536], vram[65536], oam[544]; extern u16int cgram[256], vramlatch; extern u8int mdr, mdr1, mdr2; @@ -25,7 +21,7 @@ extern u8int dspstate; extern u16int dspcounter, noise; extern int ppuclock, spcclock, dspclock, stimerclock, cpupause; -extern int battery, saveclock, scale, mouse; +extern int battery, saveclock, mouse; enum { FLAGC = 1<<0, diff --git a/sys/src/games/snes/dsp.c b/sys/src/games/snes/dsp.c index b4ad1e7f1..991c45316 100644 --- a/sys/src/games/snes/dsp.c +++ b/sys/src/games/snes/dsp.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -77,7 +78,7 @@ audioout(void) return -1; if(sbufp == sbuf) return 0; - rc = write(fd, sbuf, (sbufp - sbuf) * 2); + rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2); if(rc > 0) sbufp -= (rc+1)/2; if(sbufp < sbuf) diff --git a/sys/src/games/snes/mem.c b/sys/src/games/snes/mem.c index 6fea74bfd..885713a85 100644 --- a/sys/src/games/snes/mem.c +++ b/sys/src/games/snes/mem.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/games/snes/ppu.c b/sys/src/games/snes/ppu.c index 0ae2ccfb9..5819e032c 100644 --- a/sys/src/games/snes/ppu.c +++ b/sys/src/games/snes/ppu.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" @@ -8,7 +9,6 @@ int ppux, ppuy, rx; static u8int mode, bright, pixelpri[2], hires; static u32int pixelcol[2]; u16int vtime = 0x1ff, htime = 0x1ff, subcolor; -uchar pic[256*239*2*3]; u16int hofs[5], vofs[5]; s16int m7[6]; @@ -40,30 +40,31 @@ darken(u16int v) static void pixeldraw(int x, int y, u16int v, int s) { - uchar *p; - u16int *q; + u16int *p; union { u16int w; u8int b[2]; } u; if(bright != 0xf && s >= 0) v = darken(v); - if(scale == 1){ - p = pic + (x + y * 256) * 2; - p[0] = v; - p[1] = v >> 8; - return; - } + p = (u16int *)pic + (x + y * 256) * scale; u.b[0] = v; u.b[1] = v >> 8; - if(scale == 2){ - q = (u16int*)pic + (x + y * 256) * 2; - if(s < 1) - q[0] = u.w; - q[1] = u.w; - }else{ - q = (u16int*)pic + (x + y * 256) * 3; - q[0] = u.w; - q[1] = u.w; - q[2] = u.w; + switch(scale){ + case 16: *p++ = u.w; + case 15: *p++ = u.w; + case 14: *p++ = u.w; + case 13: *p++ = u.w; + case 12: *p++ = u.w; + case 11: *p++ = u.w; + case 10: *p++ = u.w; + case 9: *p++ = u.w; + case 8: *p++ = u.w; + case 7: *p++ = u.w; + case 6: *p++ = u.w; + case 5: *p++ = u.w; + case 4: *p++ = u.w; + case 3: *p++ = u.w; + case 2: if(s < 1) *p++ = u.w; + default: *p = u.w; } } diff --git a/sys/src/games/snes/snes.c b/sys/src/games/snes/snes.c index 863247fef..3e43b631d 100644 --- a/sys/src/games/snes/snes.c +++ b/sys/src/games/snes/snes.c @@ -4,21 +4,16 @@ #include <draw.h> #include <keyboard.h> #include <mouse.h> -#include <ctype.h> +#include <emu.h> #include "dat.h" #include "fns.h" uchar *prg, *sram; int nprg, nsram, hirom, battery; -int ppuclock, spcclock, dspclock, stimerclock, saveclock, msgclock, paused, perfclock, cpupause; -Mousectl *mc; -Channel *flushc, *msgc; -QLock pauselock; -u32int keys; -int savefd, scale, profile, mouse, loadreq, savereq; -Rectangle picr; -Image *tmp, *bg; +int ppuclock, spcclock, dspclock, stimerclock, saveclock, msgclock, cpupause; +Channel *msgc; +int savefd, mouse; void flushram(void) @@ -114,187 +109,13 @@ loadbat(char *file) } void -keyproc(void *) -{ - int fd, n, k; - static char buf[256]; - char *s; - Rune r; - - fd = open("/dev/kbd", OREAD); - if(fd < 0) - sysfatal("open: %r"); - for(;;){ - if(buf[0] != 0){ - n = strlen(buf)+1; - memmove(buf, buf+n, sizeof(buf)-n); - } - if(buf[0] == 0){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0) - sysfatal("read /dev/kbd: %r"); - buf[n-1] = 0; - buf[n] = 0; - } - if(buf[0] == 'c'){ - if(utfrune(buf, KF|5)) - savereq = 1; - if(utfrune(buf, KF|6)) - loadreq = 1; - if(utfrune(buf, Kdel)){ - close(fd); - threadexitsall(nil); - } - if(utfrune(buf, 't')) - trace = !trace; - } - if(buf[0] != 'k' && buf[0] != 'K') - continue; - s = buf + 1; - k = 0xffff; - while(*s != 0){ - s += chartorune(&r, s); - switch(r){ - case Kdel: close(fd); threadexitsall(nil); - case 'z': k |= 1<<31; break; - case 'x': k |= 1<<23; break; - case 'a': k |= 1<<30; break; - case 's': k |= 1<<22; break; - case 'q': k |= 1<<21; break; - case 'w': k |= 1<<20; break; - case Kshift: k |= 1<<29; break; - case 10: k |= 1<<28; break; - case Kup: k |= 1<<27; break; - case Kdown: k |= 1<<26; break; - case Kleft: k |= 1<<25; break; - case Kright: k |= 1<<24; break; - case Kesc: - if(paused) - qunlock(&pauselock); - else - qlock(&pauselock); - paused = !paused; - break; - } - } - if(!mouse) - keys = k; - } -} - -void -screeninit(void) -{ - Point p; - - p = divpt(addpt(screen->r.min, screen->r.max), 2); - picr = (Rectangle){subpt(p, Pt(scale * 128, scale * 112)), addpt(p, Pt(scale * 128, scale * 127))}; - if(tmp != nil) freeimage(tmp); - tmp = allocimage(display, Rect(0, 0, scale * 256, scale > 1 ? 1 : scale * 239), RGB15, scale > 1, 0); - if(bg != nil) freeimage(bg); - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - draw(screen, screen->r, bg, nil, ZP); -} - -void -screenproc(void *) -{ - extern uchar pic[256*239*2*3]; - char *s; - Mouse m; - Point p; - - enum { AMOUSE, ARESIZE, AFLUSH, AMSG, AEND }; - Alt a[AEND+1] = { - { mc->c, &m, CHANRCV }, - { mc->resizec, nil, CHANRCV }, - { flushc, nil, CHANRCV }, - { msgc, &s, CHANRCV }, - { nil, nil, CHANEND } - }; - - for(;;){ - switch(alt(a)){ - case AMOUSE: - if(mouse && ptinrect(m.xy, picr)){ - p = subpt(m.xy, picr.min); - p.x /= scale; - p.y /= scale; - keys = keys & 0xff3f0000 | p.x | p.y << 8; - if((m.buttons & 1) != 0) - keys |= 1<<22; - if((m.buttons & 4) != 0) - keys |= 1<<23; - if((m.buttons & 2) != 0) - lastkeys = keys; - } - break; - case ARESIZE: - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - /* wet floor */ - case AFLUSH: - if(scale == 1){ - loadimage(tmp, tmp->r, pic, 256*239*2); - draw(screen, picr, tmp, nil, ZP); - } else { - Rectangle r; - uchar *s; - int w; - - s = pic; - r = picr; - w = 256*2*scale; - while(r.min.y < picr.max.y){ - loadimage(tmp, tmp->r, s, w); - s += w; - r.max.y = r.min.y+scale; - draw(screen, r, tmp, nil, ZP); - r.min.y = r.max.y; - } - } - flushimage(display, 1); - break; - case AMSG: - draw(screen, rectaddpt(Rect(10, 10, 200, 30), screen->r.min), bg, nil, ZP); - if(s != nil){ - string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, - display->defaultfont, s); - free(s); - } - break; - } - } -} - -void -timing(void) -{ - static vlong old; - vlong new; - - new = nsec(); - if(new != old) - message("%6.2f%%", 1e11 / (new - old)); - old = nsec(); -} - -void threadmain(int argc, char **argv) { int t; extern u16int pc; - scale = 1; hirom = -1; ARGBEGIN { - case '2': - scale = 2; - break; - case '3': - scale = 3; - break; case 'a': audioinit(); break; @@ -308,9 +129,6 @@ threadmain(int argc, char **argv) case 'h': hirom++; break; - case 'T': - profile++; - break; default: goto usage; } ARGEND; @@ -321,16 +139,20 @@ usage: threadexitsall("usage"); } loadrom(argv[0]); - if(initdraw(nil, nil, argv0) < 0) - sysfatal("initdraw: %r"); - flushc = chancreate(sizeof(ulong), 1); - msgc = chancreate(sizeof(char*), 0); - mc = initmouse(nil, screen); - if(mc == nil) - sysfatal("initmouse: %r"); - screeninit(); - proccreate(keyproc, 0, 8192); - proccreate(screenproc, 0, 8192); + initemu(256, 239, 2, RGB15, !mouse, nil); + regkey("b", 'z', 1<<31); + regkey("a", 'x', 1<<23); + regkey("y", 'a', 1<<30); + regkey("x", 's', 1<<22); + regkey("l1", 'q', 1<<21); + regkey("r1", 'w', 1<<20); + regkey("control", Kshift, 1<<29); + regkey("start", '\n', 1<<28); + regkey("up", Kup, 1<<27); + regkey("down", Kdown, 1<<26); + regkey("left", Kleft, 1<<25); + regkey("right", Kright, 1<<24); + msgc = chancreate(sizeof(char*), 1); loadbat(argv[0]); cpureset(); memreset(); @@ -358,7 +180,6 @@ usage: stimerclock += t; ppuclock += t; dspclock += t; - perfclock -= t; while(ppuclock >= 4){ ppustep(); @@ -386,18 +207,43 @@ usage: msgclock = 0; } } - if(profile && perfclock <= 0){ - perfclock = FREQ; - timing(); - } } } void flush(void) { - sendul(flushc, 1); /* flush screen */ - audioout(); + char *s; + Mouse m; + Point p; + + extern Rectangle picr; + extern Mousectl *mc; + flushmouse(!mouse); + while(nbrecv(mc->c, &m) > 0){ + if(ptinrect(m.xy, picr)){ + p = subpt(m.xy, picr.min); + p.x /= scale; + p.y /= scale; + keys = keys & 0xff3f0000 | p.x | p.y << 8; + if((m.buttons & 1) != 0) + keys |= 1<<22; + if((m.buttons & 4) != 0) + keys |= 1<<23; + if((m.buttons & 2) != 0) + lastkeys = keys; + } + } + flushscreen(); + while(nbrecv(msgc, &s) > 0){ + if(s != nil){ + string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, + display->defaultfont, s); + free(s); + flushimage(display, 1); + } + } + flushaudio(audioout); } void diff --git a/sys/src/games/snes/spc.c b/sys/src/games/snes/spc.c index 43c1b7695..a5fc7ab8a 100644 --- a/sys/src/games/snes/spc.c +++ b/sys/src/games/snes/spc.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <thread.h> +#include <emu.h> #include "dat.h" #include "fns.h" diff --git a/sys/src/libemu/emu.c b/sys/src/libemu/emu.c new file mode 100644 index 000000000..908727b75 --- /dev/null +++ b/sys/src/libemu/emu.c @@ -0,0 +1,316 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <keyboard.h> +#include <mouse.h> +#include <emu.h> + +typedef struct Kfn Kfn; + +u64int keys, keys2; +int trace, paused; +int savereq, loadreq; +QLock pauselock; +int scale, warp10; +uchar *pic; +Rectangle picr; +Mousectl *mc; +Image *bg; + +static int profile, framestep; +static int vwdx, vwdy, vwbpp; +static ulong vwchan; +static Image *fb; + +struct Kfn{ + Rune r; + int k; + char joyk[16]; + void(*fn)(void); + Kfn *n; +}; +Kfn kfn, kkn; + +void * +emalloc(ulong sz) +{ + void *v; + + v = mallocz(sz, 1); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&sz)); + return v; +} + +static void +joyproc(void *) +{ + char *s, *down[9]; + static char buf[64]; + int n, k, j; + Kfn *kp; + + j = 1; + + for(;;){ + n = read(0, buf, sizeof(buf) - 1); + if(n <= 0) + sysfatal("read: %r"); + buf[n] = 0; + n = getfields(buf, down, nelem(down), 1, " "); + k = 0; + for(n--; n >= 0; n--){ + s = down[n]; + if(strcmp(s, "joy1") == 0) + j = 1; + else if(strcmp(s, "joy2") == 0) + j = 2; + for(kp=kkn.n; kp!=nil; kp=kp->n){ + if(strcmp(kp->joyk, s) == 0) + k |= kp->k; + } + } + if(j == 2) + keys2 = k; + else + keys = k; + } +} + +static void +keyproc(void *) +{ + int fd, n, k; + static char buf[256]; + char *s; + Rune r; + Kfn *kp; + + fd = open("/dev/kbd", OREAD); + if(fd < 0) + sysfatal("open: %r"); + for(;;){ + if(buf[0] != 0){ + n = strlen(buf)+1; + memmove(buf, buf+n, sizeof(buf)-n); + } + if(buf[0] == 0){ + n = read(fd, buf, sizeof(buf)-1); + if(n <= 0) + sysfatal("read /dev/kbd: %r"); + buf[n-1] = 0; + buf[n] = 0; + } + if(buf[0] == 'c'){ + if(utfrune(buf, Kdel)){ + close(fd); + threadexitsall(nil); + } + if(utfrune(buf, KF|5)) + savereq = 1; + if(utfrune(buf, KF|6)) + loadreq = 1; + if(utfrune(buf, KF|12)) + profile ^= 1; + if(utfrune(buf, 't')) + trace = !trace; + for(kp=kfn.n; kp!=nil; kp=kp->n){ + if(utfrune(buf, kp->r)) + kp->fn(); + } + } + if(buf[0] != 'k' && buf[0] != 'K') + continue; + s = buf + 1; + k = 0; + while(*s != 0){ + s += chartorune(&r, s); + switch(r){ + case Kdel: close(fd); threadexitsall(nil); + case Kesc: + if(paused) + qunlock(&pauselock); + else + qlock(&pauselock); + paused = !paused; + break; + case KF|1: + if(paused){ + qunlock(&pauselock); + paused=0; + } + framestep = !framestep; + break; + case '`': + warp10 = !warp10; + break; + } + for(kp=kkn.n; kp!=nil; kp=kp->n){ + if(utfrune(buf, kp->r)) + k |= kp->k; + } + } + k &= ~(k << 1 & 0xa0 | k >> 1 & 0x50); + keys = k; + } +} + +static void +timing(void) +{ + static int fcount; + static vlong old; + static char buf[32]; + vlong new; + + if(++fcount == 60) + fcount = 0; + else + return; + new = nsec(); + if(new != old) + sprint(buf, "%6.2f%%", 1e11 / (new - old)); + else + buf[0] = 0; + draw(screen, rectaddpt(Rect(10, 10, vwdx-40, 30), screen->r.min), bg, nil, ZP); + string(screen, addpt(screen->r.min, Pt(10, 10)), display->black, ZP, display->defaultfont, buf); + old = nsec(); +} + +static void +screeninit(void) +{ + Point p; + + scale = Dx(screen->r) / vwdx; + if(scale <= 0) + scale = 1; + else if(scale > 16) + scale = 16; + p = divpt(addpt(screen->r.min, screen->r.max), 2); + picr = Rpt(subpt(p, Pt(scale * vwdx/2, scale * vwdy/2)), + addpt(p, Pt(scale * vwdx/2, scale * vwdy/2))); + freeimage(fb); + fb = allocimage(display, Rect(0, 0, scale * vwdx, scale > 1 ? 1 : scale * vwdy), + vwchan, scale > 1, 0); + free(pic); + pic = emalloc(vwdx * vwdy * vwbpp * scale); + draw(screen, screen->r, bg, nil, ZP); +} + +void +flushmouse(int discard) +{ + Mouse m; + + if(nbrecvul(mc->resizec) > 0){ + if(getwindow(display, Refnone) < 0) + sysfatal("resize failed: %r"); + screeninit(); + } + if(discard) + while(nbrecv(mc->c, &m) > 0) + ; +} + +void +flushscreen(void) +{ + flushmouse(1); + if(scale == 1){ + loadimage(fb, fb->r, pic, vwdx * vwdy * vwbpp); + draw(screen, picr, fb, nil, ZP); + } else { + Rectangle r; + uchar *s; + int w; + + s = pic; + r = picr; + w = vwdx * vwbpp * scale; + while(r.min.y < picr.max.y){ + loadimage(fb, fb->r, s, w); + s += w; + r.max.y = r.min.y+scale; + draw(screen, r, fb, nil, ZP); + r.min.y = r.max.y; + } + } + flushimage(display, 1); + if(profile) + timing(); +} + +void +flushaudio(int (*audioout)(void)) +{ + static vlong old, delta; + vlong new, diff; + + if(audioout == nil || audioout() < 0 && !warp10){ + new = nsec(); + diff = 0; + if(old != 0){ + diff = BILLION/60 - (new - old) - delta; + if(diff >= MILLION) + sleep(diff/MILLION); + } + old = nsec(); + if(diff > 0){ + diff = (old - new) - (diff / MILLION) * MILLION; + delta += (diff - delta) / 100; + } + } + if(framestep){ + paused = 1; + qlock(&pauselock); + framestep = 0; + } +} + +void +regkeyfn(Rune r, void (*fn)(void)) +{ + Kfn *kp; + + for(kp=&kfn; kp->n!=nil; kp=kp->n) + ; + kp->n = emalloc(sizeof *kp); + kp->n->r = r; + kp->n->fn = fn; +} + +void +regkey(char *joyk, Rune r, int k) +{ + Kfn *kp; + + for(kp=&kkn; kp->n!=nil; kp=kp->n) + ; + kp->n = emalloc(sizeof *kp); + strncpy(kp->n->joyk, joyk, sizeof(kp->n->joyk)-1); + kp->n->r = r; + kp->n->k = k; +} + +void +initemu(int dx, int dy, int bpp, ulong chan, int dokey, void(*kproc)(void*)) +{ + vwdx = dx; + vwdy = dy; + vwchan = chan; + vwbpp = bpp; + if(initdraw(nil, nil, nil) < 0) + sysfatal("initdraw: %r"); + mc = initmouse(nil, screen); + if(mc == nil) + sysfatal("initmouse: %r"); + if(dokey) + proccreate(kproc != nil ? kproc : keyproc, nil, mainstacksize); + if(kproc == nil) + proccreate(joyproc, nil, mainstacksize*2); + bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); + screeninit(); +} diff --git a/sys/src/libemu/mkfile b/sys/src/libemu/mkfile new file mode 100644 index 000000000..f436124a2 --- /dev/null +++ b/sys/src/libemu/mkfile @@ -0,0 +1,20 @@ +</$objtype/mkfile + +LIB=/$objtype/lib/libemu.a + +OFILES=\ + emu.$O\ + +HFILES=\ + /sys/include/draw.h\ + /sys/include/emu.h\ + /sys/include/mouse.h\ + /sys/include/keyboard.h + +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + ${LIB:/$objtype/%=/386/%}\ + +</sys/src/cmd/mksyslib |