diff --git a/sys/src/games/nes/apu.c b/sys/src/games/nes/apu.c index f34704506..53b851d86 100644 --- a/sys/src/games/nes/apu.c +++ b/sys/src/games/nes/apu.c @@ -5,10 +5,11 @@ #include "dat.h" #include "fns.h" +enum { MAXBUF = 2000 }; + u8int apuseq, apuctr[10]; static int fd; - -enum { RATE = 44100 }; +static short sbuf[2*MAXBUF], *sbufp; int targperiod(int i) @@ -204,31 +205,36 @@ dmc(void) return 0; } -static void -sample(short *s) +void +audiosample(void) { double d; + if(sbufp == nil) + return; d = 95.88 / (8128.0 / (0.01 + pulse(0) + pulse(1)) + 100); d += 159.79 / (1.0 / (0.01 + tri()/8227.0 + noise()/12241.0 + dmc()/22638.0) + 100.0); - *s++ = d * 20000; - *s = d * 20000; + if(sbufp < sbuf + nelem(sbuf) - 1){ + *sbufp++ = d * 20000; + *sbufp++ = d * 20000; + } } -static void -audioproc(void *) +int +audioout(void) { - static short samples[500 * 2]; - int i; + int rc; - for(;;){ - if(paused) - memset(samples, 0, sizeof samples); - else - for(i = 0; i < sizeof samples/4; i++) - sample(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 @@ -237,7 +243,7 @@ initaudio(void) fd = open("/dev/audio", OWRITE); if(fd < 0) return; - proccreate(audioproc, nil, 8192); + sbufp = sbuf; } u8int apulen[32] = { diff --git a/sys/src/games/nes/dat.h b/sys/src/games/nes/dat.h index 3e56023e8..be58a805b 100644 --- a/sys/src/games/nes/dat.h +++ b/sys/src/games/nes/dat.h @@ -76,6 +76,8 @@ enum { MILLION = 1000000, BILLION = 1000000000, APUDIV = 89490, + RATE = 44100, + SAMPDIV = FREQ / RATE, SAVEFREQ = FREQ/5, }; diff --git a/sys/src/games/nes/fns.h b/sys/src/games/nes/fns.h index 0dab3df5f..cb82000d9 100644 --- a/sys/src/games/nes/fns.h +++ b/sys/src/games/nes/fns.h @@ -11,3 +11,5 @@ void put8(u8int); int get8(void); void apustep(void); void initaudio(void); +void audiosample(void); +int audioout(void); diff --git a/sys/src/games/nes/nes.c b/sys/src/games/nes/nes.c index a50a4908a..a283825ce 100644 --- a/sys/src/games/nes/nes.c +++ b/sys/src/games/nes/nes.c @@ -13,7 +13,7 @@ uchar *prg, *chr; int scale; Rectangle picr; Image *tmp, *bg; -int clock, ppuclock, apuclock, syncclock, syncfreq, checkclock, msgclock, saveclock, sleeps; +int clock, ppuclock, apuclock, sampclock, msgclock, saveclock; Mousectl *mc; int keys, paused, savereq, loadreq, oflag, savefd = -1; int mirr; @@ -184,7 +184,6 @@ threadmain(int argc, char **argv) { int t, h, sflag; Point p; - uvlong old, new, diff; scale = 1; h = 240; @@ -231,8 +230,6 @@ threadmain(int argc, char **argv) pc = memread(0xFFFC) | memread(0xFFFD) << 8; rP = FLAGI; - syncfreq = FREQ / 30; - old = nsec(); for(;;){ if(savereq){ savestate("nes.save"); @@ -250,8 +247,9 @@ threadmain(int argc, char **argv) clock += t; ppuclock += t; apuclock += t; - syncclock += t; - checkclock += t; + sampclock += t; + //syncclock += t; + //checkclock += t; while(ppuclock >= 4){ ppustep(); ppuclock -= 4; @@ -260,24 +258,9 @@ threadmain(int argc, char **argv) apustep(); apuclock -= APUDIV; } - if(syncclock >= syncfreq){ - sleep(10); - sleeps++; - syncclock = 0; - } - if(checkclock >= FREQ){ - new = nsec(); - diff = new - old - sleeps * 10 * MILLION; - diff = BILLION - diff; - if(diff <= 0) - syncfreq = FREQ; - else - syncfreq = ((vlong)FREQ) * 10 * MILLION / diff; - if(syncfreq < FREQ / 100) - syncfreq = FREQ / 100; - old = new; - checkclock = 0; - sleeps = 0; + if(sampclock >= SAMPDIV){ + audiosample(); + sampclock -= SAMPDIV; } if(msgclock > 0){ msgclock -= t; diff --git a/sys/src/games/nes/ppu.c b/sys/src/games/nes/ppu.c index fd788d561..3c7c320fd 100644 --- a/sys/src/games/nes/ppu.c +++ b/sys/src/games/nes/ppu.c @@ -255,6 +255,8 @@ flush(void) extern Rectangle picr; extern Image *tmp, *bg; extern Mousectl *mc; + static vlong old, diff; + vlong new; Mouse m; Point p; int h; @@ -282,6 +284,15 @@ flush(void) 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(); + if(old != 0){ + diff = BILLION/60 - (new - old); + if(diff >= MILLION) + sleep(diff/MILLION); + } + old = new; + } } void