shithub: sms

Download patch

ref: 23fe5dd09ffe2e3c2d925945bc1adcbf6fc6fc97
parent: 6dc689653c52eb5db90d3adf00f0d1ab2caacc0e
author: Jean-André Santoni <jean.andre.santoni@gmail.com>
date: Thu Mar 12 10:02:10 EDT 2026

Improve psg

--- a/psg.c
+++ b/psg.c
@@ -8,7 +8,6 @@
 static int fd;
 static short sbuf[2 * 2000], *sbufp;
 
-static const u8int noise_table[3] = { 0x10, 0x20, 0x40 };
 static const short vol_table[16] = {
 	8191, 6507, 5168, 4105, 3261, 2590, 2057,
 	1642, 1298, 1031, 819, 650, 516, 410, 326, 0
@@ -21,9 +20,25 @@
 static u8int attn[4];
 static int flipflop[4];
 static u16int noise;
+static int noiseflip;
+static int noiseout;
 static u8int curr_reg;
 static u8int curr_type;
 
+static void
+psgreset(void)
+{
+	memset(freqreg, 0, sizeof freqreg);
+	memset(countreg, 0, sizeof countreg);
+	memset(flipflop, 0, sizeof flipflop);
+	memset(attn, 0x0f, sizeof attn);
+	noise = 0x8000;
+	noiseflip = 0;
+	noiseout = 0;
+	curr_reg = 0;
+	curr_type = 0;
+}
+
 void
 psgwrite(const u8int data)
 {
@@ -37,14 +52,15 @@
 
 	if(curr_type){
 		attn[curr_reg] = data & 0x0F;
-	}else if(first && curr_reg == 3){
+	}else if(curr_reg == 3){
 		freqreg[3] = data & 7;
 		noise = 0x8000;
-	}
-	else if(first)
+		noiseflip = 0;
+		noiseout = 0;
+	}else if(first)
 		freqreg[curr_reg] = (freqreg[curr_reg] & 0x3F0) | (data & 0x0F);
 	else
-		countreg[curr_reg] = freqreg[curr_reg] = (freqreg[curr_reg] & 0x0F) | ((data & 0x3F) << 4);
+		freqreg[curr_reg] = (freqreg[curr_reg] & 0x0F) | ((data & 0x3F) << 4);
 }
 
 static inline u16int
@@ -61,30 +77,45 @@
 static inline s16int
 vol(u8int chn)
 {
-	return (flipflop[chn] ? 1 : -1) * vol_table[attn[chn]];
+	int on;
+
+	on = chn == 3 ? noiseout : flipflop[chn];
+	return (on ? 1 : -1) * vol_table[attn[chn]];
 }
 
-u16int
-psgstep(void)
+static inline void
+toneclock(u8int chn)
 {
-	while(cyc > 0){
-		for(u8int i = 0; i < 4; i++){
-			countreg[i]--;
-			if(!countreg[i]){
-				if(i < 3){
-					countreg[i] = freqreg[i];
-					flipflop[i] = !flipflop[i];
-				}else{
-					u8int nf = freqreg[3] & 3;
-					u8int fb = (freqreg[3] >> 2) & 1;
-					countreg[3] = nf == 3 ? freqreg[2] : (0x10 << nf);
+	if(countreg[chn] == 0 || --countreg[chn] == 0){
+		countreg[chn] = freqreg[chn];
+		flipflop[chn] ^= 1;
+	}
+}
 
-					noise = (noise >> 1) | ((fb ? parity(noise & 0x9) : noise & 1) << 15);
-					flipflop[3] = (noise & 1);
-				}
-			}
+static inline void
+noiseclock(void)
+{
+	u8int nf, fb;
+
+	nf = freqreg[3] & 3;
+	fb = (freqreg[3] >> 2) & 1;
+	if(countreg[3] == 0 || --countreg[3] == 0){
+		countreg[3] = nf == 3 ? freqreg[2] : (0x10 << nf);
+		if((noiseflip ^= 1) != 0){
+			noiseout = noise & 1;
+			noise = (noise >> 1) | ((fb ? parity(noise & 0x9) : noise & 1) << 15);
 		}
+	}
+}
 
+u16int
+psgstep(void)
+{
+	while(cyc > 0){
+		toneclock(0);
+		toneclock(1);
+		toneclock(2);
+		noiseclock();
 		cyc--;
 	}
 
@@ -130,6 +161,7 @@
 {
 	cyclespersample = (double)clockspd / (double)PSGDIV/ (double)rate;
 	cyc = cyclespersample;
+	psgreset();
 
 	fd = open("/dev/audio", OWRITE);
 	if(fd < 0)
--