diff options
| author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-11-18 16:07:34 +0100 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-11-18 16:07:34 +0100 |
| commit | 763231588c971758d36c7c48cd073f2fa96f8f5a (patch) | |
| tree | 7980a7614ae86d504065e5bb82ecfc18cb62a0be | |
| parent | 844612fcb8257c8d8f20ef4da62edb65b2c08b76 (diff) | |
| download | plan9front-763231588c971758d36c7c48cd073f2fa96f8f5a.tar.xz | |
games/snes: flush screen in parallel to audio (fixes buffer underruns on x200s)
the x200s is too slow on a single core to keep up without
audio buffer underruns, so the idea is to flush screen
in parallel to witing audio samples in a separate process.
with the proc, we also can keep updating the screen on resize
when paused.
| -rw-r--r-- | sys/src/games/snes/snes.c | 112 |
1 files changed, 68 insertions, 44 deletions
diff --git a/sys/src/games/snes/snes.c b/sys/src/games/snes/snes.c index ebb99d714..9316ebd0d 100644 --- a/sys/src/games/snes/snes.c +++ b/sys/src/games/snes/snes.c @@ -13,6 +13,7 @@ int nprg, nsram, hirom, battery; int ppuclock, spcclock, dspclock, stimerclock, saveclock, msgclock, paused, perfclock, cpupause; Mousectl *mc; +Channel *flushc; QLock pauselock; u32int keys; int savefd, scale, profile, mouse, loadreq, savereq; @@ -185,6 +186,68 @@ screeninit(void) } void +screenproc(void *) +{ + extern uchar pic[256*240*2*3]; + Mouse m; + Point p; + + enum { AMOUSE, ARESIZE, AFLUSH, AEND }; + Alt a[AEND+1] = { + { mc->c, &m, CHANRCV }, + { mc->resizec, nil, CHANRCV }, + { flushc, nil, 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; + } + } +} + +void timing(void) { static vlong old; @@ -242,14 +305,16 @@ usage: threadexitsall("usage"); } loadrom(argv[0]); - if(initdraw(nil, nil, nil) < 0) + 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(); - loadbat(argv[0]); proccreate(keyproc, 0, 8192); + proccreate(screenproc, 0, 8192); + loadbat(argv[0]); cpureset(); memreset(); spcreset(); @@ -314,48 +379,7 @@ usage: void flush(void) { - extern uchar pic[256*240*2*3]; - Mouse m; - Point p; - - if(nbrecvul(mc->resizec) > 0){ - if(getwindow(display, Refnone) < 0) - sysfatal("resize failed: %r"); - screeninit(); - } - while(nbrecv(mc->c, &m) > 0) - 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; - } - 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); + sendul(flushc, 1); /* flush screen */ audioout(); } |
