games/nes: best commit (fixed audio and timing)

This commit is contained in:
aiju 2014-02-24 19:33:26 +01:00
parent ad9047ab2c
commit 9486df09c2
5 changed files with 47 additions and 43 deletions

View file

@ -5,10 +5,11 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
enum { MAXBUF = 2000 };
u8int apuseq, apuctr[10]; u8int apuseq, apuctr[10];
static int fd; static int fd;
static short sbuf[2*MAXBUF], *sbufp;
enum { RATE = 44100 };
int int
targperiod(int i) targperiod(int i)
@ -204,31 +205,36 @@ dmc(void)
return 0; return 0;
} }
static void void
sample(short *s) audiosample(void)
{ {
double d; double d;
if(sbufp == nil)
return;
d = 95.88 / (8128.0 / (0.01 + pulse(0) + pulse(1)) + 100); 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); d += 159.79 / (1.0 / (0.01 + tri()/8227.0 + noise()/12241.0 + dmc()/22638.0) + 100.0);
*s++ = d * 20000; if(sbufp < sbuf + nelem(sbuf) - 1){
*s = d * 20000; *sbufp++ = d * 20000;
*sbufp++ = d * 20000;
}
} }
static void int
audioproc(void *) audioout(void)
{ {
static short samples[500 * 2]; int rc;
int i;
for(;;){ if(sbufp == nil)
if(paused) return -1;
memset(samples, 0, sizeof samples); if(sbufp == sbuf)
else return 0;
for(i = 0; i < sizeof samples/4; i++) rc = write(fd, sbuf, (sbufp - sbuf) * 2);
sample(samples + 2 * i); if(rc > 0)
write(fd, samples, sizeof samples); sbufp -= (rc+1)/2;
} if(sbufp < sbuf)
sbufp = sbuf;
return 0;
} }
void void
@ -237,7 +243,7 @@ initaudio(void)
fd = open("/dev/audio", OWRITE); fd = open("/dev/audio", OWRITE);
if(fd < 0) if(fd < 0)
return; return;
proccreate(audioproc, nil, 8192); sbufp = sbuf;
} }
u8int apulen[32] = { u8int apulen[32] = {

View file

@ -76,6 +76,8 @@ enum {
MILLION = 1000000, MILLION = 1000000,
BILLION = 1000000000, BILLION = 1000000000,
APUDIV = 89490, APUDIV = 89490,
RATE = 44100,
SAMPDIV = FREQ / RATE,
SAVEFREQ = FREQ/5, SAVEFREQ = FREQ/5,
}; };

View file

@ -11,3 +11,5 @@ void put8(u8int);
int get8(void); int get8(void);
void apustep(void); void apustep(void);
void initaudio(void); void initaudio(void);
void audiosample(void);
int audioout(void);

View file

@ -13,7 +13,7 @@ uchar *prg, *chr;
int scale; int scale;
Rectangle picr; Rectangle picr;
Image *tmp, *bg; Image *tmp, *bg;
int clock, ppuclock, apuclock, syncclock, syncfreq, checkclock, msgclock, saveclock, sleeps; int clock, ppuclock, apuclock, sampclock, msgclock, saveclock;
Mousectl *mc; Mousectl *mc;
int keys, paused, savereq, loadreq, oflag, savefd = -1; int keys, paused, savereq, loadreq, oflag, savefd = -1;
int mirr; int mirr;
@ -184,7 +184,6 @@ threadmain(int argc, char **argv)
{ {
int t, h, sflag; int t, h, sflag;
Point p; Point p;
uvlong old, new, diff;
scale = 1; scale = 1;
h = 240; h = 240;
@ -231,8 +230,6 @@ threadmain(int argc, char **argv)
pc = memread(0xFFFC) | memread(0xFFFD) << 8; pc = memread(0xFFFC) | memread(0xFFFD) << 8;
rP = FLAGI; rP = FLAGI;
syncfreq = FREQ / 30;
old = nsec();
for(;;){ for(;;){
if(savereq){ if(savereq){
savestate("nes.save"); savestate("nes.save");
@ -250,8 +247,9 @@ threadmain(int argc, char **argv)
clock += t; clock += t;
ppuclock += t; ppuclock += t;
apuclock += t; apuclock += t;
syncclock += t; sampclock += t;
checkclock += t; //syncclock += t;
//checkclock += t;
while(ppuclock >= 4){ while(ppuclock >= 4){
ppustep(); ppustep();
ppuclock -= 4; ppuclock -= 4;
@ -260,24 +258,9 @@ threadmain(int argc, char **argv)
apustep(); apustep();
apuclock -= APUDIV; apuclock -= APUDIV;
} }
if(syncclock >= syncfreq){ if(sampclock >= SAMPDIV){
sleep(10); audiosample();
sleeps++; sampclock -= SAMPDIV;
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(msgclock > 0){ if(msgclock > 0){
msgclock -= t; msgclock -= t;

View file

@ -255,6 +255,8 @@ flush(void)
extern Rectangle picr; extern Rectangle picr;
extern Image *tmp, *bg; extern Image *tmp, *bg;
extern Mousectl *mc; extern Mousectl *mc;
static vlong old, diff;
vlong new;
Mouse m; Mouse m;
Point p; Point p;
int h; int h;
@ -282,6 +284,15 @@ flush(void)
loadimage(screen, picr, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale); loadimage(screen, picr, pic + oflag*8*256*4*scale*scale, 256*h*4*scale*scale);
flushimage(display, 1); flushimage(display, 1);
memset(pic, sizeof pic, 0); 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 void