How to properly reset the APU?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
How to properly reset the APU?
by on (#228623)
I have very little knowledge about the APU since I have been using from the start libraries like famitracker or famitone. One issue that I have by using the famitracker driver is that it doesn't reset the APU: it expect the song to set properly for the song, which is not always the case.

Which mean, in some case, if the APU is not reset, the effects from the last song persist, which causes the song to not play properly. I'm sure some people would say "then just make sure the song doesn't do that", I know, but since I have some song were I only have the bin data, I cannot do that.

From a programmer point of view, the issue is that the APU is not in it initial state before playing the song so I would like to add that code to the driver so this issue won't occur anymore.

Is such reset code exist? I'm not aware of that. If such code exist, I will be more than happy to read it and understand how it works if pointed in the right direction.

Thank you in advance for information on this subject.
Re: How to properly reset the APU?
by on (#228626)
I think you're right.

FamiToneMusicStop resets the song, and stops DMC samples, but doesn't stop sound effect streams.

You could create a sound effect of just note cuts, and call that to play.
Re: How to properly reset the APU?
by on (#228627)
There is other case like the noise channel, when you change the, hmmm, tone (?), it stays too.

So the simplest would be to create an empty song that resets everything, that could be a temporary fix for now. Would still love to understand how to do it by code with the registers, if the cause is the nes registers stays in the last state OR the driver is the cause. This is the other part that I'm not sure yet.
Re: How to properly reset the APU?
by on (#228629)
Have you tried other drivers? I'm pretty sure that starting a song in Pently will clear all effects. If you need specific help integrating Pently, feel free to shoot me a private message.
Re: How to properly reset the APU?
by on (#228630)
Does this work?
Code:
  lda #0
  tax
:
  sta $4000, x
  inx
  cpx #$14
  bne :-
Re: How to properly reset the APU?
by on (#228632)
Quote:
There is other case like the noise channel, when you change the, hmmm, tone (?), it stays too.


I haven't seen that problem.

Are you sure you, in Famitracker, in the song, have checked the box for a duty cycle on the noise instrument?


Quote:
Does this work?


If there is still a sound effect stream going, it won't work, because famitone will keep writing to the APU registers until the effect is completed.
Re: How to properly reset the APU?
by on (#228649)
@tepples

It nice of you but unfortunately for this specific project I cannot change driver. I may look at the code so I can fix my current issue, if pubby's example doesn't fix it in the first place. I may consider your driver on my next project, which I hope to start once I finish the one I'm working right now, which is helping me study more about the nes ;)

@pubby

I don't know yet but I will try. It it does reset the APU to the same state when doing a cold reset then yes, that is what I'm looking for.

@dougeff

Like I mentioned, when you have a binary blob that cannot be edited, you cannot go to famitracker to fix it. In that case, my goal is before starting the next song, call a method that would set back all channel to their cold reset state value. The problem is, I don't know what those values are supposed to be and if you need to reset all channel/register etc since I have little knowledge on the subject yet. The simplest way is just to make sure that all song's instruments sets their attributes properly so this problem won't happen but right now I can't. I just want to fix it programmatically, instead of hoping that all songs are set properly.

For the noise channel, I proper example after looking at the wiki is that the song set the bit 7 of $400E so the noise would be metallic like. The song finishes and you load the next song but for some reason, the instruments in that song didn't set the noise channel bit 7 to 0 since in the editor, this is the default value. So the song plays fine in the player, fine if played first but fail when playing after a song that set that bit. I don't think the bit is set by the driver when the second song is loaded but more the nes APU is still with $400E with bit 7 set, which would make sense.

So my goal is to reset all those register with their original value, like it I would have did a cold reset but I don't know what they are. I don't remember seeing any example of that like the example that explain how to set the stack, set memory to 0, wait 2 vblank, 4017 irq reset etc when you reset the nes.
Re: How to properly reset the APU?
by on (#228652)
The very quick way to silence the APU is just to write 0 to $4015. Do that first.

If you want, you can also write 0 to each of the registers, but a music engine should be initializing all of these itself anyway.

I suppose I like to set the starting values to something more specific in my APU initialization, but the only thing I would particularly point out is that if you're not using the sweep I think it's best to write $7F to both sweep registers to minimize their "silencing" effect that will cut off some of the bass range of the squares if set to 0 (info here).

As for why Famitracker doesn't initialize everything, I think that's because it's written for NSF, which has a guaranteed setup, see:
Wiki: NSF - Initializing a tune
Re: How to properly reset the APU?
by on (#228654)
rainwarrior wrote:
If you want, you can also write 0 to each of the registers, but a music engine should be initializing all of these itself anyway.


Not for the noise channel though, it's the only one where 0 is a valid frequency. It will make a little tap sound. If you ever hear that in early NES demos, it's that (or maybe it was just my programs that did that.. it's a familiar sound to me).
Re: How to properly reset the APU?
by on (#228656)
Memblers wrote:
Not for the noise channel though, it's the only one where 0 is a valid frequency. It will make a little tap sound. If you ever hear that in early NES demos, it's that (or maybe it was just my programs that did that.. it's a familiar sound to me).

If you write 0 to $4105 before you begin it won't make any sound no matter what you write to $4000-4013.

For an explanation of why it'd make a noise: writing 0 to the volume register for the squares and noise puts it in envelope mode, rather than silence, but in the case of the squares they'll get silenced by the sweep unit by being set to frequency zero. In the case of noise writing the 0 to its length counter means that envelope will get silenced after 10 ticks of the length counter (5 frames). The triangle gets silenced more quickly because it has the additional "linear counter" device.

Write to $4015 first though and none of this matters. ;) That's why I said you can also write 0s if you want.
Re: How to properly reset the APU?
by on (#228657)
Writing zero to 4011 can cause a little pop sound, if it wasn't already zero.
Re: How to properly reset the APU?
by on (#228658)
Today I learned a lot of new things about the APU so I want to thanks everyone about it :)

As for my issue, after more testing, this is more something with the driver after all and will put it on my low priority of something that "I want to know why it does that" :lol:

In brief, I was doing a reset before starting the song with all the things I learned but it was not fixing anything. So I tested with a song that set "v01" in the noise effect column then played a song which doesn't set it. Even though the reset code was there, nothing was happening: "v01" was still active in the new song. So I updated the song with "v01" and added "v00" at the end and now the second song works because, well, I just set back to what it should. But my point is, from that test, there is a good chance that the famitracker driver cache the column effects somewhere and when you load a new song, if nothing is written in that column, the previous effects persists somehow. So, I may have found a small bug but for now I don't know the driver enough so I will just use the workaround to either modify the song, when possible, or just play a song that just fix those effects.

Thanks everyone again for the information! I need to start to play with the APU for real someday ^^;;
Re: How to properly reset the APU?
by on (#228662)
The link I posted above might help:
rainwarrior wrote:
As for why Famitracker doesn't initialize everything, I think that's because it's written for NSF, which has a guaranteed setup, see:
Wiki: NSF - Initializing a tune


If you look at the list of init steps for NSF, you can see that Famitracker is allowed to rely not only on the APU being initialized, but all its RAM being set to 0 before INIT is called.
Re: How to properly reset the APU?
by on (#228664)
rainwarrior wrote:
If you look at the list of init steps for NSF, you can see that Famitracker is allowed to rely not only on the APU being initialized, but all its RAM being set to 0 before INIT is called.


Doh :lol: It was right in my face and I didn't realize it. If it expect that the memory is cleared on each play then yes, that would explain why in a game that doesn't reset the FT rams on every play that some effects could still be set. That make sense!

I will add to my todo list to add a method to reset the ram before play. My list of bugfix is getting big so for now this one will be in the lower priority.

I need to learn to read too :D