mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-22 20:45:11 +00:00
NES: add 20xx effect for changing DPCM freq
This commit is contained in:
parent
bd53c57658
commit
0c0472ce76
4 changed files with 54 additions and 4 deletions
|
@ -42,6 +42,30 @@ also known as Famicom. it is a five-channel sound generator: first two channels
|
|||
- `00`: PCM (software).
|
||||
- `01`: DPCM (hardware).
|
||||
- when in DPCM mode, samples will sound muffled (due to its nature), availables pitches are limited and loop point is ignored.
|
||||
- `20xx`: set DPCM frequency.
|
||||
- only works in DPCM mode.
|
||||
- see table below for possible values.
|
||||
|
||||
# DPCM frequency table
|
||||
|
||||
val | NTSC | PAL
|
||||
----|-----------|-----------
|
||||
00 | 4181.7Hz | 4177.4Hz
|
||||
01 | 4709.9Hz | 4696.6Hz
|
||||
02 | 5264.0Hz | 5261.4Hz
|
||||
03 | 5593.0Hz | 5579.2Hz
|
||||
04 | 6257.9Hz | 6023.9Hz
|
||||
05 | 7046.3Hz | 7044.9Hz
|
||||
06 | 7919.3Hz | 7917.2Hz
|
||||
07 | 8363.4Hz | 8397.0Hz
|
||||
08 | 9419.9Hz | 9446.6Hz
|
||||
09 | 11186.1Hz | 11233.8Hz
|
||||
0A | 12604.0Hz | 12595.5Hz
|
||||
0B | 13982.6Hz | 14089.9Hz
|
||||
0C | 16884.6Hz | 16965.4Hz
|
||||
0D | 21306.8Hz | 21315.5Hz
|
||||
0E | 24858.0Hz | 25191.0Hz
|
||||
0F | 33143.9Hz | 33252.1Hz
|
||||
|
||||
# length counter table
|
||||
|
||||
|
|
|
@ -337,14 +337,22 @@ void DivPlatformNES::tick(bool sysTick) {
|
|||
goingToLoop=parent->getSample(dacSample)->isLoopable();
|
||||
// write DPCM
|
||||
rWrite(0x4015,15);
|
||||
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
|
||||
if (nextDPCMFreq>=0) {
|
||||
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
|
||||
nextDPCMFreq=-1;
|
||||
} else {
|
||||
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
|
||||
}
|
||||
rWrite(0x4012,(dpcmAddr>>6)&0xff);
|
||||
rWrite(0x4013,dpcmLen&0xff);
|
||||
rWrite(0x4015,31);
|
||||
dpcmBank=dpcmAddr>>14;
|
||||
}
|
||||
} else {
|
||||
if (dpcmMode) {
|
||||
if (nextDPCMFreq>=0) {
|
||||
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
|
||||
nextDPCMFreq=-1;
|
||||
} else {
|
||||
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +361,8 @@ void DivPlatformNES::tick(bool sysTick) {
|
|||
if (chan[4].keyOn) chan[4].keyOn=false;
|
||||
chan[4].freqChanged=false;
|
||||
}
|
||||
|
||||
nextDPCMFreq=-1;
|
||||
}
|
||||
|
||||
int DivPlatformNES::dispatch(DivCommand c) {
|
||||
|
@ -406,7 +416,12 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
goingToLoop=parent->getSample(dacSample)->isLoopable();
|
||||
// write DPCM
|
||||
rWrite(0x4015,15);
|
||||
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
|
||||
if (nextDPCMFreq>=0) {
|
||||
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
|
||||
nextDPCMFreq=-1;
|
||||
} else {
|
||||
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
|
||||
}
|
||||
rWrite(0x4012,(dpcmAddr>>6)&0xff);
|
||||
rWrite(0x4013,dpcmLen&0xff);
|
||||
rWrite(0x4015,31);
|
||||
|
@ -555,6 +570,14 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
rWrite(0x4013,0);
|
||||
rWrite(0x4015,31);
|
||||
break;
|
||||
case DIV_CMD_SAMPLE_FREQ: {
|
||||
bool goingToLoop=parent->getSample(dacSample)->isLoopable();
|
||||
if (dpcmMode) {
|
||||
nextDPCMFreq=c.value&15;
|
||||
rWrite(0x4010,(c.value&15)|(goingToLoop?0x40:0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SAMPLE_BANK:
|
||||
sampleBank=c.value;
|
||||
if (sampleBank>(parent->song.sample.size()/12)) {
|
||||
|
@ -658,6 +681,7 @@ void DivPlatformNES::reset() {
|
|||
dpcmMode=dpcmModeDefault;
|
||||
goingToLoop=false;
|
||||
countMode=false;
|
||||
nextDPCMFreq=-1;
|
||||
|
||||
if (useNP) {
|
||||
nes1_NP->Reset();
|
||||
|
|
|
@ -52,6 +52,7 @@ class DivPlatformNES: public DivDispatch {
|
|||
unsigned char sampleBank;
|
||||
unsigned char writeOscBuf;
|
||||
unsigned char apuType;
|
||||
signed char nextDPCMFreq;
|
||||
bool dpcmMode;
|
||||
bool dpcmModeDefault;
|
||||
bool dacAntiClickOn;
|
||||
|
|
|
@ -712,7 +712,8 @@ void DivEngine::registerSystems() {
|
|||
{0x15, {DIV_CMD_NES_ENV_MODE, "15xx: Set envelope mode (0: envelope, 1: length, 2: looping, 3: constant)"}},
|
||||
{0x16, {DIV_CMD_NES_LENGTH, "16xx: Set length counter (refer to manual for a list of values)"}},
|
||||
{0x17, {DIV_CMD_NES_COUNT_MODE, "17xx: Set frame counter mode (0: 4-step, 1: 5-step)"}},
|
||||
{0x18, {DIV_CMD_SAMPLE_MODE, "18xx: Select PCM/DPCM mode (0: PCM; 1: DPCM)"}}
|
||||
{0x18, {DIV_CMD_SAMPLE_MODE, "18xx: Select PCM/DPCM mode (0: PCM; 1: DPCM)"}},
|
||||
{0x20, {DIV_CMD_SAMPLE_FREQ, "20xx: Set DPCM frequency (0 to F)"}}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue