ref: 9486df09c2455ee3b22df8507db77e7d7276ad58
parent: ad9047ab2cdbdbc5897d799fecacdda98f6cd707
author: aiju <devnull@localhost>
date: Mon Feb 24 14:33:26 EST 2014
games/nes: best commit (fixed audio and timing)
--- a/sys/src/games/nes/apu.c
+++ b/sys/src/games/nes/apu.c
@@ -5,11 +5,12 @@
#include "dat.h"
#include "fns.h"
+enum { MAXBUF = 2000 };
+
u8int apuseq, apuctr[10];
static int fd;
+static short sbuf[2*MAXBUF], *sbufp;
-enum { RATE = 44100 };
-
int
targperiod(int i)
{
@@ -204,31 +205,36 @@
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 @@
fd = open("/dev/audio", OWRITE);
if(fd < 0)
return;
- proccreate(audioproc, nil, 8192);
+ sbufp = sbuf;
}
u8int apulen[32] = {
--- a/sys/src/games/nes/dat.h
+++ b/sys/src/games/nes/dat.h
@@ -76,6 +76,8 @@
MILLION = 1000000,
BILLION = 1000000000,
APUDIV = 89490,
+ RATE = 44100,
+ SAMPDIV = FREQ / RATE,
SAVEFREQ = FREQ/5,
};
--- a/sys/src/games/nes/fns.h
+++ b/sys/src/games/nes/fns.h
@@ -11,3 +11,5 @@
int get8(void);
void apustep(void);
void initaudio(void);
+void audiosample(void);
+int audioout(void);
--- a/sys/src/games/nes/nes.c
+++ b/sys/src/games/nes/nes.c
@@ -13,7 +13,7 @@
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 @@
{
int t, h, sflag;
Point p;
- uvlong old, new, diff;
scale = 1;
h = 240;
@@ -231,8 +230,6 @@
pc = memread(0xFFFC) | memread(0xFFFD) << 8;
rP = FLAGI;
- syncfreq = FREQ / 30;
- old = nsec();
for(;;){
if(savereq){
savestate("nes.save");
@@ -250,8 +247,9 @@
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 @@
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;
--- a/sys/src/games/nes/ppu.c
+++ b/sys/src/games/nes/ppu.c
@@ -255,6 +255,8 @@
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 @@
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