Interrupt question

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
za909
Posts: 229
Joined: Fri Jan 24, 2014 9:05 am
Location: Hungary

Interrupt question

Post by za909 »

So I need to know this before designing my sound engine and NMI a certain way... I want to use two 16+1 byte "dummy" DMC samples to apply volume control to the triangle channel (the noise channel inconsistency I can get rid of easily) one of them being all $00 bytes and the other $FF bytes embedded into my Init code so that it doesn't have to take more space from the fixed bank. But in the meantime I also want to use my percussive samples, so what I would have to do is make a version of each drum I need that sets the IRQ flag. The loading process is pretty straightforward, I have a table with $1F entries (the upper 3 bits being the note length) for each of the 4 DMC registers, so a $4011 write is also assigned to every one of them. What I would do when I want to keep the triangle volume down is playing the drum, and when the IRQ fires, play the $FF ramp immediately.

But what if this IRQ happens to fire during NMI, or during my OAM transfer? Does the IRQ fire at all? And if so, can it potentially mess with my transfer? If it's not reliable I will give up on this approach, I can also imagine the IRQ firing right when my wait for the end of VBlank is about to end and this happens and I lose some time and return to game logic a bit late.
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Interrupt question

Post by lidnariq »

za909 wrote:But what if this IRQ happens to fire during NMI
As long as your NMI doesn't clear the IRQ enable bit and doesn't write to the APU status register, the IRQ will remain asserted. If it is asserted, it will be handled as soon as the NMI finishes.

Yes, that means you could miss your reload window if your NMI handler takes too long.

Consider instead having two copies of each DMC instrument such that it will end at +max or -max on the APU DMC DAC when the sample completes instead.
or during my OAM transfer?
APU DMC correctly steals cycles from OAM DMA.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Interrupt question

Post by rainwarrior »

As an alternative to using an IRQ or two versions of the samples, you could just poll $4015, and start your ramp sample when the DMC flag is clear (i.e. the sample is finished). 1 frame of latency on the volume control probably wouldn't be bad at all.
User avatar
za909
Posts: 229
Joined: Fri Jan 24, 2014 9:05 am
Location: Hungary

Re: Interrupt question

Post by za909 »

Thank you, yes I think I'll go with running this once per frame:
(apu2vol can be set to 0 or 1 with effect commands)

Code: Select all

ldy #$40
	lda APUchenable
	sty APUframecnt
	and #$10 ; if DMC is not playing atm, play the right ramp sample
	bne +isactive ; skip ramp loading
	ldy apu2vol
	lda #$07
	sta APUdpcmpitch
	lda APU2Vol_TBL,y ; select ramp
	sta APUdpcmaddr
	lda #$01
	sta APUdpcmlength
	lda #$1F
	sta APUchenable
I'm not sure if writing to the frame counter is necessary, but I got freaked out when I read this on the wiki about $4015 reads: "Reading this register clears the frame interrupt flag (but not the DMC interrupt flag)." I'm not sure if the thing mentioned here is the interrupt inhibit flag in $4017 or the internal state of it.
It's basically no problem because I always play these at pitch 7, so I lose around 40 cycles from the NMI at most, but a sample at pitch F (which does happen) will steal around 168 cycles from my NMI anyway.

This could also make it trivial to write to $4011 when I start a "real" sample because the signal will either stick to $00 or $7F by default, and I also don't have to destroy the end of my samples completely with Famitracker's tilting function.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Interrupt question

Post by rainwarrior »

Reading $4015 doesn't clear the interrupt inhibit flag in $4017. It clears the frame counter's internal flag that signals the interrupt itself (i.e. "acknowledges" the IRQ).
Post Reply