summaryrefslogtreecommitdiff
path: root/sys/src/games/eui.c
diff options
context:
space:
mode:
authorqwx <devnull@localhost>2018-05-13 07:01:47 +0200
committerqwx <devnull@localhost>2018-05-13 07:01:47 +0200
commit88537cfe9b483846ccd7367c81fde5dcfe16a4d5 (patch)
tree29277160129a844585f281045b368cd64776d8a2 /sys/src/games/eui.c
parentabf8c8bf2cd27541d6a102f7c0385c3fe281f578 (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.c316
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();
+}