Update apu sweep unit

- http://wiki.nesdev.com/w/index.php/APU_Sweep
- APU sweep test roms:
   https://forums.nesdev.com/viewtopic.php?t=219&p=1403
- Fixes R.C. Pro AM II intro music
This commit is contained in:
retro-wertz
2018-12-08 08:42:33 +08:00
parent 64bccb470a
commit 68c5289726

View File

@@ -70,6 +70,7 @@ static int32 RectDutyCount[2];
static uint8 sweepon[2];
static int32 curfreq[2];
static uint8 SweepCount[2];
static uint8 sweepReload[2];
static uint16 nreg = 0;
@@ -183,13 +184,9 @@ static void SQReload(int x, uint8 V) {
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;
EnvUnits[x].reloaddec = 1;
/* reloadfreq[x]=1; */
}
static DECLFW(Write_PSG) {
@@ -204,7 +201,9 @@ static DECLFW(Write_PSG) {
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
break;
case 0x1:
sweepon[0] = V & 0x80;
DoSQ1();
sweepReload[0] = 1;
sweepon[0] = (V & 0x80);
break;
case 0x2:
DoSQ1();
@@ -222,7 +221,9 @@ static DECLFW(Write_PSG) {
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
break;
case 0x5:
sweepon[1] = V & 0x80;
DoSQ2();
sweepReload[1] = 1;
sweepon[1] = (V & 0x80);
break;
case 0x6:
DoSQ2();
@@ -371,34 +372,25 @@ static void FASTAPASS(1) FrameSoundStuff(int V) {
/* Frequency Sweep Code Here */
/* xxxx 0000 */
/* xxxx = hz. 120/(x+1)*/
if (sweepon[P]) {
int32 mod = 0;
if (SweepCount[P] > 0) SweepCount[P]--;
if (SweepCount[P] <= 0) {
SweepCount[P] = ((PSG[(P << 2) + 0x1] >> 4) & 7) + 1; /* +1; */
/* http://wiki.nesdev.com/w/index.php/APU_Sweep */
if (SweepCount[P] > 0) SweepCount[P]--;
if (SweepCount[P] <= 0) {
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) {
mod -= (P ^ 1) + ((curfreq[P]) >> (PSG[(P << 2) + 0x1] & 7));
if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) {
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 + (P ^ 1));
} else if ((mod + curfreq[P]) < 0x800) {
curfreq[P] += mod;
}
}
} else {/* Sweeping is disabled: */
#if 0
curfreq[P]&=0xFF00;
curfreq[P]|=PSG[(P<<2)|0x2]; /* |((PSG[(P<<2)|3]&7)<<8); */
#endif
SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
}
if (sweepReload[P]) {
SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
sweepReload[P] = 0;
}
}
}