diff options
author | aiju <devnull@localhost> | 2014-02-27 19:52:02 +0100 |
---|---|---|
committer | aiju <devnull@localhost> | 2014-02-27 19:52:02 +0100 |
commit | ff5ac0c5cb11cf2770a44157107abff8536a0edc (patch) | |
tree | 390f4923481387c70255c325a42156f95da827a1 | |
parent | c65a3809dade0640fe6247fecb9461515857aec2 (diff) | |
download | plan9front-ff5ac0c5cb11cf2770a44157107abff8536a0edc.tar.xz |
games/nes: improved time synchronization
games/gb: added some games/nes improvements
-rw-r--r-- | sys/src/games/gb/audio.c | 71 | ||||
-rw-r--r-- | sys/src/games/gb/dat.h | 1 | ||||
-rw-r--r-- | sys/src/games/gb/fns.h | 5 | ||||
-rw-r--r-- | sys/src/games/gb/gb.c | 83 | ||||
-rw-r--r-- | sys/src/games/gb/ppu.c | 15 | ||||
-rw-r--r-- | sys/src/games/nes/ppu.c | 13 |
6 files changed, 95 insertions, 93 deletions
diff --git a/sys/src/games/gb/audio.c b/sys/src/games/gb/audio.c index 0af1c0418..4ee36457d 100644 --- a/sys/src/games/gb/audio.c +++ b/sys/src/games/gb/audio.c @@ -9,7 +9,7 @@ static int fd; static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v; extern int paused; -enum { SAMPLE = 44100 }; +static short sbuf[2*2000], *sbufp; static int thresh(int f, int b) @@ -84,12 +84,14 @@ envelope(int *v, int *c) (*c)++; } -static void -dosample(short *smp) +void +audiosample(void) { int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s; u8int f; + if(sbufp == nil) + return; if(sc >= SAMPLE/256){ soundlen(0xFF11, 0xFF14, 0); soundlen(0xFF16, 0xFF19, 1); @@ -179,51 +181,40 @@ dosample(short *smp) ch4s *= ch4v >> 4; ch4s *= 8000 / 0xF; - smp[0] = 0; - smp[1] = 0; f = mem[0xFF25]; r = mem[0xFF26] & 15; r = r | (r << 4); f &= r; - if(f & 0x01) smp[0] += ch1s; - if(f & 0x02) smp[0] += ch2s; - if(f & 0x04) smp[0] += ch3s; - if(f & 0x08) smp[0] += ch4s; - if(f & 0x10) smp[1] += ch1s; - if(f & 0x20) smp[1] += ch2s; - if(f & 0x40) smp[1] += ch3s; - if(f & 0x80) smp[1] += ch4s; -} - -void -setpri(int pri) -{ - char buf[64]; - int fd; - - snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); - if((fd = open(buf, OWRITE)) >= 0){ - fprint(fd, "pri %d\n", pri); - close(fd); + if(sbufp < sbuf + nelem(sbuf) - 1){ + *sbufp = 0; + if(f & 0x01) *sbufp += ch1s; + if(f & 0x02) *sbufp += ch2s; + if(f & 0x04) *sbufp += ch3s; + if(f & 0x08) *sbufp += ch4s; + *++sbufp = 0; + if(f & 0x10) *sbufp += ch1s; + if(f & 0x20) *sbufp += ch2s; + if(f & 0x40) *sbufp += ch3s; + if(f & 0x80) *sbufp += ch4s; + sbufp++; } } -void -audioproc(void *) +int +audioout(void) { - short samples[10 * 2]; - int i; + int rc; - setpri(13); - - for(;;){ - if(paused) - memset(samples, 0, sizeof samples); - else - for(i = 0; i < sizeof samples/4; i++) - dosample(samples + 2 * i); - write(fd, samples, sizeof samples); - } + if(sbufp == nil) + return -1; + if(sbufp == sbuf) + return 0; + rc = write(fd, sbuf, (sbufp - sbuf) * 2); + if(rc > 0) + sbufp -= (rc+1)/2; + if(sbufp < sbuf) + sbufp = sbuf; + return 0; } void @@ -236,5 +227,5 @@ initaudio(void) fd = open("/dev/audio", OWRITE); if(fd < 0) return; - proccreate(audioproc, nil, 8192); + sbufp = sbuf; } diff --git a/sys/src/games/gb/dat.h b/sys/src/games/gb/dat.h index ce33d6d24..6c5509453 100644 --- a/sys/src/games/gb/dat.h +++ b/sys/src/games/gb/dat.h @@ -77,4 +77,5 @@ enum { MILLION = 1000000, BILLION = 1000000000, + SAMPLE = 44100, }; diff --git a/sys/src/games/gb/fns.h b/sys/src/games/gb/fns.h index 8d43d223b..42b7203c6 100644 --- a/sys/src/games/gb/fns.h +++ b/sys/src/games/gb/fns.h @@ -8,4 +8,7 @@ void message(char *, ...); void flushram(void); void savestate(char *); void loadstate(char *); -void initaudio(void);
\ No newline at end of file +void initaudio(void); +void audiosample(void); +int audioout(void); +void flush(void); diff --git a/sys/src/games/gb/gb.c b/sys/src/games/gb/gb.c index e1edd9043..b7382b38d 100644 --- a/sys/src/games/gb/gb.c +++ b/sys/src/games/gb/gb.c @@ -9,7 +9,7 @@ #include "fns.h" uchar *cart, *ram; -int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, syncclock, syncfreq, sleeps, checkclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale, paused; +int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, audioclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale, paused; Rectangle picr; Image *bg, *tmp; Mousectl *mc; @@ -143,8 +143,7 @@ loadrom(char *file) p = divpt(addpt(screen->r.min, screen->r.max), 2); picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))}; bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - if(screen->chan != XRGB32 || screen->chan != XBGR32) - tmp = allocimage(display, Rect(0, 0, scale * 160, scale * 144), XRGB32, 0, 0); + tmp = allocimage(display, Rect(0, 0, scale * 160, scale * 144), XRGB32, 0, 0); draw(screen, screen->r, bg, nil, ZP); if(ram && battery){ @@ -234,9 +233,6 @@ void threadmain(int argc, char** argv) { int t; - vlong old, new, diff; - Mouse m; - Point p; scale = 1; ARGBEGIN{ @@ -267,8 +263,6 @@ threadmain(int argc, char** argv) if(mc == nil) sysfatal("init mouse: %r"); proccreate(keyproc, nil, 8192); - syncfreq = CPUFREQ / 50; - old = nsec(); for(;;){ if(savereq){ savestate("gb.save"); @@ -286,26 +280,20 @@ threadmain(int argc, char** argv) clock += t; ppuclock += t; divclock += t; + audioclock += t; timerclock += t; - syncclock += t; - checkclock += t; if(ppuclock >= 456){ ppustep(); ppuclock -= 456; - 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 * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))}; - bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF); - } } if(divclock >= 256){ mem[DIV]++; divclock = 0; } + if(audioclock >= CPUFREQ / SAMPLE){ + audiosample(); + audioclock -= CPUFREQ / SAMPLE; + } if(timer && timerclock >= timerfreq){ mem[TIMA]++; if(mem[TIMA] == 0){ @@ -314,23 +302,6 @@ threadmain(int argc, char** argv) } timerclock = 0; } - if(syncclock >= syncfreq){ - sleep(10); - sleeps++; - syncclock = 0; - } - if(checkclock >= CPUFREQ){ - new = nsec(); - diff = new - old - sleeps * 10 * MILLION; - diff = BILLION - diff; - if(diff <= 0) - syncfreq = CPUFREQ; - else - syncfreq = ((vlong)CPUFREQ) * 10 * MILLION / diff; - old = new; - checkclock = 0; - sleeps = 0; - } if(msgclock > 0){ msgclock -= t; if(msgclock <= 0){ @@ -340,3 +311,43 @@ threadmain(int argc, char** argv) } } } + +void +flush(void) +{ + extern uchar pic[160*144*4*3*3]; + Mouse m; + Point p; + static vlong old; + vlong new, diff; + + 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 * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))}; + 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){ + loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale); + draw(screen, picr, tmp, nil, ZP); + }else + loadimage(screen, picr, pic, 160*144*4*scale*scale); + flushimage(display, 1); + memset(pic, sizeof pic, 0); + if(audioout() < 0){ + new = nsec(); + if(old != 0){ + diff = BILLION/60 - (new - old); + if(diff >= MILLION) + sleep(diff/MILLION); + } + old = nsec(); + } +} diff --git a/sys/src/games/gb/ppu.c b/sys/src/games/gb/ppu.c index 920ce2d42..f36b7c484 100644 --- a/sys/src/games/gb/ppu.c +++ b/sys/src/games/gb/ppu.c @@ -177,9 +177,6 @@ drawwindow(void) void ppustep(void) { - extern Rectangle picr; - extern Image *tmp; - if(mem[LY] == 144){ mem[STAT] &= ~3; mem[STAT] |= 1; @@ -204,14 +201,8 @@ ppustep(void) mem[LY]++; if(mem[LY] > 160){ mem[LY] = 0; - if(mem[LCDC] & LCDOP){ - if(tmp){ - loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale); - draw(screen, picr, tmp, nil, ZP); - }else - loadimage(screen, picr, pic, 160*144*4*scale*scale); - flushimage(display, 1); - memset(pic, sizeof pic, 0); - } + if((mem[LCDC] & LCDOP) == 0) + memset(pic, 0, sizeof(pic)); + flush(); } } diff --git a/sys/src/games/nes/ppu.c b/sys/src/games/nes/ppu.c index 3c7c320fd..3cb4a150c 100644 --- a/sys/src/games/nes/ppu.c +++ b/sys/src/games/nes/ppu.c @@ -255,8 +255,8 @@ flush(void) extern Rectangle picr; extern Image *tmp, *bg; extern Mousectl *mc; - static vlong old, diff; - vlong new; + static vlong old, delta; + vlong new, diff; Mouse m; Point p; int h; @@ -286,12 +286,17 @@ flush(void) memset(pic, sizeof pic, 0); if(audioout() < 0){ new = nsec(); + diff = 0; if(old != 0){ - diff = BILLION/60 - (new - old); + diff = BILLION/60 - (new - old) - delta; if(diff >= MILLION) sleep(diff/MILLION); } - old = new; + old = nsec(); + if(diff != 0){ + diff = (old - new) - (diff / MILLION) * MILLION; + delta += (diff - delta) / 100; + } } } |