mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
nes_apu.cpp: Improvements for triangle channel. (#9310)
- Don't set output level to zero, it is always determined by sequencer, which cannot be reset. This eliminates most of the popping, hopefully. - Raised artificial frequency cutoff to about 18KHz instead of 11KHz. - Added linear counter reload flag.
This commit is contained in:
parent
2db924e5ec
commit
50668b5d5a
@ -202,6 +202,7 @@ void nesapu_device::device_start()
|
|||||||
|
|
||||||
save_item(NAME(m_APU.tri.regs));
|
save_item(NAME(m_APU.tri.regs));
|
||||||
save_item(NAME(m_APU.tri.linear_length));
|
save_item(NAME(m_APU.tri.linear_length));
|
||||||
|
save_item(NAME(m_APU.tri.linear_reload));
|
||||||
save_item(NAME(m_APU.tri.vbl_length));
|
save_item(NAME(m_APU.tri.vbl_length));
|
||||||
save_item(NAME(m_APU.tri.write_latency));
|
save_item(NAME(m_APU.tri.write_latency));
|
||||||
save_item(NAME(m_APU.tri.phaseacc));
|
save_item(NAME(m_APU.tri.phaseacc));
|
||||||
@ -209,7 +210,6 @@ void nesapu_device::device_start()
|
|||||||
save_item(NAME(m_APU.tri.counter_started));
|
save_item(NAME(m_APU.tri.counter_started));
|
||||||
save_item(NAME(m_APU.tri.enabled));
|
save_item(NAME(m_APU.tri.enabled));
|
||||||
save_item(NAME(m_APU.tri.output));
|
save_item(NAME(m_APU.tri.output));
|
||||||
save_item(NAME(m_APU.tri.output_next));
|
|
||||||
|
|
||||||
save_item(NAME(m_APU.noi.regs));
|
save_item(NAME(m_APU.noi.regs));
|
||||||
save_item(NAME(m_APU.noi.seed));
|
save_item(NAME(m_APU.noi.seed));
|
||||||
@ -328,19 +328,17 @@ void nesapu_device::apu_square(apu_t::square_t *chan)
|
|||||||
/* OUTPUT TRIANGLE WAVE SAMPLE (VALUES FROM 0 to +15) */
|
/* OUTPUT TRIANGLE WAVE SAMPLE (VALUES FROM 0 to +15) */
|
||||||
void nesapu_device::apu_triangle(apu_t::triangle_t *chan)
|
void nesapu_device::apu_triangle(apu_t::triangle_t *chan)
|
||||||
{
|
{
|
||||||
int freq;
|
|
||||||
/* reg0: 7=holdnote, 6-0=linear length counter
|
/* reg0: 7=holdnote, 6-0=linear length counter
|
||||||
** reg2: low 8 bits of frequency
|
** reg2: low 8 bits of frequency
|
||||||
** reg3: 7-3=length counter, 2-0=high 3 bits of frequency
|
** reg3: 7-3=length counter, 2-0=high 3 bits of frequency
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!chan->enabled)
|
if (!chan->enabled)
|
||||||
{
|
|
||||||
chan->output = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!chan->counter_started && !(chan->regs[0] & 0x80))
|
bool not_held = !BIT(chan->regs[0], 7);
|
||||||
|
|
||||||
|
if (!chan->counter_started && not_held)
|
||||||
{
|
{
|
||||||
if (chan->write_latency)
|
if (chan->write_latency)
|
||||||
chan->write_latency--;
|
chan->write_latency--;
|
||||||
@ -350,45 +348,37 @@ void nesapu_device::apu_triangle(apu_t::triangle_t *chan)
|
|||||||
|
|
||||||
if (chan->counter_started)
|
if (chan->counter_started)
|
||||||
{
|
{
|
||||||
if (chan->linear_length > 0)
|
if (chan->linear_reload)
|
||||||
|
chan->linear_length = m_sync_times2[chan->regs[0] & 0x7f];
|
||||||
|
else if (chan->linear_length > 0)
|
||||||
chan->linear_length--;
|
chan->linear_length--;
|
||||||
if (chan->vbl_length && !(chan->regs[0] & 0x80))
|
|
||||||
chan->vbl_length--;
|
|
||||||
|
|
||||||
if (!chan->vbl_length)
|
if (not_held)
|
||||||
{
|
chan->linear_reload = false;
|
||||||
chan->output = 0;
|
|
||||||
return;
|
if (chan->vbl_length && not_held)
|
||||||
}
|
chan->vbl_length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chan->linear_length)
|
if (!(chan->linear_length && chan->vbl_length))
|
||||||
{
|
|
||||||
chan->output = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
freq = (((chan->regs[3] & 7) << 8) + chan->regs[2]) + 1;
|
int freq = ((chan->regs[3] & 7) << 8) + chan->regs[2] + 1;
|
||||||
|
|
||||||
if (freq < 4) /* inaudible */
|
// FIXME: This halts ultrasonic frequencies. On hardware there should be some popping noise? Crash Man's stage in Mega Man 2 is an example. This can probably be removed if hardware filters are implemented (they vary by machine, NES, FC, VS, etc).
|
||||||
{
|
if (freq < 2)
|
||||||
chan->output = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
chan->phaseacc -= 4;
|
chan->phaseacc -= 4;
|
||||||
while (chan->phaseacc < 0)
|
while (chan->phaseacc < 0)
|
||||||
{
|
{
|
||||||
chan->phaseacc += freq;
|
chan->phaseacc += freq;
|
||||||
chan->adder = (chan->adder + 1) & 0x1f;
|
chan->adder++;
|
||||||
|
|
||||||
if (chan->adder & 0x10)
|
chan->output = chan->adder & 0xf;
|
||||||
chan->output_next = chan->adder & 0xf;
|
if (!BIT(chan->adder, 4))
|
||||||
else
|
chan->output ^= 0xf;
|
||||||
chan->output_next = 0xf - (chan->adder & 0xf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->output = chan->output_next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUT NOISE WAVE SAMPLE (VALUES FROM 0 to +15) */
|
/* OUTPUT NOISE WAVE SAMPLE (VALUES FROM 0 to +15) */
|
||||||
@ -610,6 +600,7 @@ inline void nesapu_device::apu_regwrite(int address, u8 value)
|
|||||||
m_APU.tri.counter_started = false;
|
m_APU.tri.counter_started = false;
|
||||||
m_APU.tri.vbl_length = m_vbl_times[value >> 3];
|
m_APU.tri.vbl_length = m_vbl_times[value >> 3];
|
||||||
m_APU.tri.linear_length = m_sync_times2[m_APU.tri.regs[0] & 0x7f];
|
m_APU.tri.linear_length = m_sync_times2[m_APU.tri.regs[0] & 0x7f];
|
||||||
|
m_APU.tri.linear_reload = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -75,6 +75,7 @@ struct apu_t
|
|||||||
|
|
||||||
uint8 regs[4]; /* regs[1] unused */
|
uint8 regs[4]; /* regs[1] unused */
|
||||||
int linear_length = 0;
|
int linear_length = 0;
|
||||||
|
bool linear_reload = false;
|
||||||
int vbl_length = 0;
|
int vbl_length = 0;
|
||||||
int write_latency = 0;
|
int write_latency = 0;
|
||||||
float phaseacc = 0.0;
|
float phaseacc = 0.0;
|
||||||
@ -82,7 +83,6 @@ struct apu_t
|
|||||||
bool counter_started = false;
|
bool counter_started = false;
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
uint8 output = 0;
|
uint8 output = 0;
|
||||||
uint8 output_next = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Noise Wave */
|
/* Noise Wave */
|
||||||
|
Loading…
Reference in New Issue
Block a user