Merge pull request #243 from retro-wertz/apu_pulse

Apu pulse
This commit is contained in:
hizzlekizzle
2018-12-08 08:51:41 -06:00
committed by GitHub

View File

@@ -70,6 +70,7 @@ static int32 RectDutyCount[2];
static uint8 sweepon[2]; static uint8 sweepon[2];
static int32 curfreq[2]; static int32 curfreq[2];
static uint8 SweepCount[2]; static uint8 SweepCount[2];
static uint8 sweepReload[2];
static uint16 nreg = 0; static uint16 nreg = 0;
@@ -84,6 +85,9 @@ int32 nesincsize = 0;
uint32 soundtsinc = 0; uint32 soundtsinc = 0;
uint32 soundtsi = 0; uint32 soundtsi = 0;
static int32 sqacc[2]; static int32 sqacc[2];
static uint32 lq_tcout;
static int32 lq_triacc;
static int32 lq_noiseacc;
/* LQ variables segment ends. */ /* LQ variables segment ends. */
static int32 lengthcount[4]; static int32 lengthcount[4];
@@ -125,9 +129,9 @@ static const uint32 PALDMCTable[0x10] =
* $4013 - Size register: Size in bytes = (V+1)*64 * $4013 - Size register: Size in bytes = (V+1)*64
*/ */
/*static*/ int32 DMCacc = 1; static int32 DMCacc = 1;
static int32 DMCPeriod = 0; static int32 DMCPeriod = 0;
/*static*/ uint8 DMCBitCount = 0; static uint8 DMCBitCount = 0;
static uint8 DMCAddressLatch = 0, DMCSizeLatch = 0; /* writes to 4012 and 4013 */ static uint8 DMCAddressLatch = 0, DMCSizeLatch = 0; /* writes to 4012 and 4013 */
static uint8 DMCFormat = 0; /* Write to $4010 */ static uint8 DMCFormat = 0; /* Write to $4010 */
@@ -175,21 +179,12 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr) {
} }
static void SQReload(int x, uint8 V) { static void SQReload(int x, uint8 V) {
if (EnabledChannels & (1 << x)) { if (EnabledChannels & (1 << x))
if (x)
DoSQ2();
else
DoSQ1();
lengthcount[x] = lengthtable[(V >> 3) & 0x1f]; lengthcount[x] = lengthtable[(V >> 3) & 0x1f];
}
sweepon[x] = PSG[(x << 2) | 1] & 0x80;
curfreq[x] = PSG[(x << 2) | 0x2] | ((V & 7) << 8);
SweepCount[x] = ((PSG[(x << 2) | 0x1] >> 4) & 7) + 1;
curfreq[x] = curfreq[x] & 0xff | ((V & 7) << 8);
RectDutyCount[x] = 7; RectDutyCount[x] = 7;
EnvUnits[x].reloaddec = 1; EnvUnits[x].reloaddec = 1;
/* reloadfreq[x]=1; */
} }
static DECLFW(Write_PSG) { static DECLFW(Write_PSG) {
@@ -204,7 +199,9 @@ static DECLFW(Write_PSG) {
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
break; break;
case 0x1: case 0x1:
sweepon[0] = V & 0x80; DoSQ1();
sweepReload[0] = 1;
sweepon[0] = (V & 0x80);
break; break;
case 0x2: case 0x2:
DoSQ1(); DoSQ1();
@@ -212,6 +209,7 @@ static DECLFW(Write_PSG) {
curfreq[0] |= V; curfreq[0] |= V;
break; break;
case 0x3: case 0x3:
DoSQ1();
SQReload(0, V); SQReload(0, V);
break; break;
case 0x4: case 0x4:
@@ -222,7 +220,9 @@ static DECLFW(Write_PSG) {
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
break; break;
case 0x5: case 0x5:
sweepon[1] = V & 0x80; DoSQ2();
sweepReload[1] = 1;
sweepon[1] = (V & 0x80);
break; break;
case 0x6: case 0x6:
DoSQ2(); DoSQ2();
@@ -230,6 +230,7 @@ static DECLFW(Write_PSG) {
curfreq[1] |= V; curfreq[1] |= V;
break; break;
case 0x7: case 0x7:
DoSQ2();
SQReload(1, V); SQReload(1, V);
break; break;
case 0xa: case 0xa:
@@ -313,6 +314,7 @@ static DECLFW(StatusWrite) {
DoTriangle(); DoTriangle();
DoNoise(); DoNoise();
DoPCM(); DoPCM();
for (x = 0; x < 4; x++) for (x = 0; x < 4; x++)
if (!(V & (1 << x))) lengthcount[x] = 0; /* Force length counters to 0. */ if (!(V & (1 << x))) lengthcount[x] = 0; /* Force length counters to 0. */
@@ -371,34 +373,25 @@ static void FASTAPASS(1) FrameSoundStuff(int V) {
/* Frequency Sweep Code Here */ /* Frequency Sweep Code Here */
/* xxxx 0000 */ /* xxxx 0000 */
/* xxxx = hz. 120/(x+1)*/ /* xxxx = hz. 120/(x+1)*/
if (sweepon[P]) { /* http://wiki.nesdev.com/w/index.php/APU_Sweep */
int32 mod = 0;
if (SweepCount[P] > 0) SweepCount[P]--; if (SweepCount[P] > 0) SweepCount[P]--;
if (SweepCount[P] <= 0) { if (SweepCount[P] <= 0) {
SweepCount[P] = ((PSG[(P << 2) + 0x1] >> 4) & 7) + 1; /* +1; */ uint32 sweepShift = (PSG[(P << 2) + 0x1] & 7);
if (sweepon[P] && sweepShift && curfreq[P] >= 8) {
int32 mod = (curfreq[P] >> sweepShift);
if (PSG[(P << 2) + 0x1] & 0x8) { if (PSG[(P << 2) + 0x1] & 0x8) {
mod -= (P ^ 1) + ((curfreq[P]) >> (PSG[(P << 2) + 0x1] & 7)); curfreq[P] -= (mod + (P ^ 1));
if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) { } else if ((mod + curfreq[P]) < 0x800) {
curfreq[P] += mod;
}
} else {
mod = curfreq[P] >> (PSG[(P << 2) + 0x1] & 7);
if ((mod + curfreq[P]) & 0x800) {
sweepon[P] = 0;
curfreq[P] = 0;
} else {
if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) {
curfreq[P] += mod; curfreq[P] += mod;
} }
} }
SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
} }
}
} else {/* Sweeping is disabled: */ if (sweepReload[P]) {
#if 0 SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
curfreq[P]&=0xFF00; sweepReload[P] = 0;
curfreq[P]|=PSG[(P<<2)|0x2]; /* |((PSG[(P<<2)|3]&7)<<8); */
#endif
} }
} }
} }
@@ -437,19 +430,21 @@ void FrameSoundUpdate(void) {
* Length counter: Bit 4-7 of $4003, $4007, $400b, $400f * Length counter: Bit 4-7 of $4003, $4007, $400b, $400f
*/ */
if (!fcnt && !(IRQFrameMode & 0x3)) {
SIRQStat |= 0x40;
X6502_IRQBegin(FCEU_IQFCOUNT);
}
if (fcnt == 3) { if (fcnt == 3) {
if (IRQFrameMode & 0x2) if (IRQFrameMode & 0x2)
fhcnt += fhinc; fhcnt += fhinc;
} }
FrameSoundStuff(fcnt); FrameSoundStuff(fcnt);
fcnt = (fcnt + 1) & 3; fcnt = (fcnt + 1) & 3;
}
/* has to be moved here to fix Dragon Warrior 4
* after irq inhibit fix for $4017 */
if (!fcnt && !(IRQFrameMode & 0x3)) {
SIRQStat |= 0x40;
X6502_IRQBegin(FCEU_IQFCOUNT);
}
}
static INLINE void tester(void) { static INLINE void tester(void) {
if (DMCBitCount == 0) { if (DMCBitCount == 0) {
@@ -476,13 +471,14 @@ static INLINE void DMCDMA(void) {
if (DMCFormat & 0x40) if (DMCFormat & 0x40)
PrepDPCM(); PrepDPCM();
else { else {
if (DMCFormat & 0x80) {
SIRQStat |= 0x80; SIRQStat |= 0x80;
if (DMCFormat & 0x80)
X6502_IRQBegin(FCEU_IQDPCM); X6502_IRQBegin(FCEU_IQDPCM);
} }
} }
} }
} }
}
void FASTAPASS(1) FCEU_SoundCPUHook(int cycles) { void FASTAPASS(1) FCEU_SoundCPUHook(int cycles) {
fhcnt -= cycles * 48; fhcnt -= cycles * 48;
@@ -536,13 +532,21 @@ static INLINE void RDoSQ(int x) {
int32 cf; int32 cf;
int32 rc; int32 rc;
if (curfreq[x] < 8 || curfreq[x] > 0x7ff) V = SOUNDTS - ChannelBC[x];
goto endit; cf = (curfreq[x] + 1) * 2;
if (!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1])) rc = wlcount[x];
goto endit;
if (!lengthcount[x])
goto endit;
/* added 2018/12/08 */
/* when pulse channel is silenced, resets length counters but not
* duty cycle, instead of resetting both */
if ((curfreq[x] < 8 || curfreq[x] > 0x7ff) ||
!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]) ||
!lengthcount[x]) {
rc -= V;
if (rc <= 0) {
rc = cf - (-rc % cf);
}
} else {
if (EnvUnits[x].Mode & 0x1) if (EnvUnits[x].Mode & 0x1)
amp = EnvUnits[x].Speed; amp = EnvUnits[x].Speed;
else else
@@ -558,15 +562,9 @@ static INLINE void RDoSQ(int x) {
amp = (amp * FSettings.SquareVolume[x]) / 256; amp = (amp * FSettings.SquareVolume[x]) / 256;
amp <<= 24; amp <<= 24;
rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6]; rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6];
D = &WaveHi[ChannelBC[x]];
V = SOUNDTS - ChannelBC[x];
currdc = RectDutyCount[x]; currdc = RectDutyCount[x];
cf = (curfreq[x] + 1) * 2; D = &WaveHi[ChannelBC[x]];
rc = wlcount[x];
while (V > 0) { while (V > 0) {
if (currdc < rthresh) if (currdc < rthresh)
@@ -581,9 +579,9 @@ static INLINE void RDoSQ(int x) {
} }
RectDutyCount[x] = currdc; RectDutyCount[x] = currdc;
wlcount[x] = rc; }
endit: wlcount[x] = rc;
ChannelBC[x] = SOUNDTS; ChannelBC[x] = SOUNDTS;
} }
@@ -728,10 +726,6 @@ static void RDoTriangle(void) {
ChannelBC[2] = SOUNDTS; ChannelBC[2] = SOUNDTS;
} }
uint32 lq_tcout = 0;
int32 lq_triacc = 0;
int32 lq_noiseacc = 0;
static void RDoTriangleNoisePCMLQ(void) { static void RDoTriangleNoisePCMLQ(void) {
int32 V; int32 V;
int32 start, end; int32 start, end;
@@ -861,7 +855,6 @@ static void RDoTriangleNoisePCMLQ(void) {
} }
} }
static void RDoNoise(void) { static void RDoNoise(void) {
uint32 V; uint32 V;
int32 outo; int32 outo;
@@ -932,10 +925,12 @@ DECLFW(Write_IRQFM) {
fcnt = 0; fcnt = 0;
if (V & 2) if (V & 2)
FrameSoundUpdate(); FrameSoundUpdate();
fcnt = 1; /* fcnt = 1; */
fhcnt = fhinc; fhcnt = fhinc;
if (V & 1) {
X6502_IRQEnd(FCEU_IQFCOUNT); X6502_IRQEnd(FCEU_IQFCOUNT);
SIRQStat &= ~0x40; SIRQStat &= ~0x40;
}
IRQFrameMode = V; IRQFrameMode = V;
} }