Once you add the DMC you'll want to minimize this as much as possible. You'll also want to have the smallest possible window between the $4015 read and $4015 write.
$4015.4 is the DMC enable bit. If it transitions from a 0->1 state, the DMC is restarted, and if you write 0, the DMC stops. So the only way to not interrupt the DMC if it is playing is to have 1->1.
The problem is, when you read $4015.4, it is 1 if the DMC is playing, and 0 if it isn't playing. So if the DMC stops playing after your read, but before you write -- you'll end up starting the DMC all over again (2 drum kicks instead of 1).
Granted... the odds of this happening would be slim, but it's one of those bugs that will pop up out of nowhere one day... and might be very hard to diagnose. (And borderline impossible to reproduce on command -- making debugging exceptionally difficult)
I wouldn't recommend the $4015 approach for this very reason. It's hard to avoid on the Tri, but I
definately would avoid it for Squares and Noise, since they can be very easily silenced by setting their volume to 0.
Another idea would be to artifically clock the length/linear counter with a $4017 write:
Code:
; silence the triangle
LDA #0
STA $4008 ; clear Linear counter control flag
LDA __whatever__
STA $400B ; set linear counter halt flag
LDA #$80
STA $4017 ; enter 5-step mode
; tri is now silenced immediately (after 1-2 CPU cycles)
This works because entering 5-step mode with the $4017 write clocks the linear counter immediately, which triggers the linear counter reload (setting the actual counter to 0, silencing the channel).
In fact -- I suspect this is why many commercial games write $80 to $4017 every frame.
Pros)
- doesn't require $4015 usage, and therefore avoids DMC troubles
Cons)
- Disrupts the natural flow of the frame sequencer. IE: you can't really use sweep/decay/etc units for a duration any longer than 1 frame.
- Can't use frame IRQs (who cares)
- Really really old or lame emus might not support it (who cares)