Page 1 of 1

APU sweep unit

Posted: Tue Apr 15, 2014 11:13 am
by Anes
I tought my sweep unit was ok, but after testing "Excitebike" in a real NES when the bike "jumps" a platform and use sweep unit my emulator is not correctly emulating it.

The code im using to emulate the sweep is this:

Code: Select all

void ClockSweep(PSWEEP PSweep, PPROGTIMER pTimer, int add)
{
	u16 result;

	if (PSweep->negate)
		result = pTimer->reload_value - (pTimer->reload_value >> PSweep->shift) + add;
	else
		result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift) + add;

	if (PSweep->divider == 0)
	{
		PSweep->dac = 1;
		
		if ((pTimer->reload_value < 8) || (result > 0x7FF && !PSweep->negate))
			PSweep->dac = 0;
		else
		if (PSweep->enable && PSweep->shift)
		{
			pTimer->reload_value = result;
		}

		PSweep->divider = PSweep->period ;
	}
	else if (PSweep->divider)
		PSweep->divider--;

	if (PSweep->write)
	{
		PSweep->divider = PSweep->period ;
		PSweep->write = 0;
	}
}

It always confused me Sweep Unit.

Any help??

Re: APU sweep unit

Posted: Tue Apr 15, 2014 11:33 am
by Quietust
I can only assume that your problem is that it doesn't sound quite right - assuming that the "add" parameter is to handle the difference between the two sweep units (i.e. where one uses two's complement negation while the other uses one's complement negation), you should only be including that when subtracting, NOT when adding.

If that isn't the problem, then you need to provide more information.

Re: APU sweep unit

Posted: Tue Apr 15, 2014 11:37 am
by Grapeshot
You should be doing

Code: Select all

result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift);
when the negate flag is off. Also I'm not sure if you're silencing it correctly.

Re: APU sweep unit

Posted: Tue Apr 15, 2014 11:55 am
by Anes
Grapeshot wrote:You should be doing

Code: Select all

result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift);
when the negate flag is off. Also I'm not sure if you're silencing it correctly.
But if we take into account:

Code: Select all

	if (PSweep->negate)
		result = pTimer->reload_value - (pTimer->reload_value >> PSweep->shift) - add;
	else
		result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift) + add;
the "else" is doing just what you say.

Then talking about silencing the routine that process sound output in my emu for a square channel is:

Code: Select all

		if (Apu.Square.Len.counter && Apu.Square.Sweep.dac && Apu.Square.Duty.dac)
				if (Apu.Square.Env.env_disable)
					out += Apu.Square.Env.env_volume;
				else
					out += Apu.Square.Env.out;

isn't that correct?

Re: APU sweep unit

Posted: Tue Apr 15, 2014 2:05 pm
by cpow
Anes wrote:
Grapeshot wrote: result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift);
if (PSweep->negate)
result = pTimer->reload_value - (pTimer->reload_value >> PSweep->shift) - add;
else
result = pTimer->reload_value + (pTimer->reload_value >> PSweep->shift) + add;

the "else" is doing just what you say.
Is it?
Anes wrote: Then talking about silencing the routine that process sound output in my emu for a square channel is:

Code: Select all

		if (Apu.Square.Len.counter && Apu.Square.Sweep.dac && Apu.Square.Duty.dac)
				if (Apu.Square.Env.env_disable)
					out += Apu.Square.Env.env_volume;
				else
					out += Apu.Square.Env.out;

isn't that correct?
I don't think so...the DAC value isn't an "input" to whether or not the channel is silenced, if I recall.

Re: APU sweep unit

Posted: Tue Apr 15, 2014 3:28 pm
by Anes
cpow wrote:I don't think so...the DAC value isn't an "input" to whether or not the channel is silenced, if I recall.
So how does it do to silence the channel?