shithub: riscv

Download patch

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