diff options
author | qwx <devnull@localhost> | 2018-05-13 07:01:47 +0200 |
---|---|---|
committer | qwx <devnull@localhost> | 2018-05-13 07:01:47 +0200 |
commit | 88537cfe9b483846ccd7367c81fde5dcfe16a4d5 (patch) | |
tree | 29277160129a844585f281045b368cd64776d8a2 /sys/src/games/eui.c | |
parent | abf8c8bf2cd27541d6a102f7c0385c3fe281f578 (diff) |
demote libemu to common code
- too small, nothing else that won't be under /games will use it
- "libemu" as a name doesn't make sense here
Diffstat (limited to 'sys/src/games/eui.c')
-rw-r--r-- | sys/src/games/eui.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/sys/src/games/eui.c b/sys/src/games/eui.c new file mode 100644 index 000000000..d462c76d8 --- /dev/null +++ b/sys/src/games/eui.c @@ -0,0 +1,316 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <keyboard.h> +#include <mouse.h> +#include "eui.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(); +} |