This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Play 2 DMC samples in sequence

Play 2 DMC samples in sequence
by on (#236599)
I want to play two samples in sequence (I'm using Famitone2), so I did an attempt with irq this way:
Code:
somewhere:
   cli ; enable irq
   lda #sample1
   jsr FamiToneSamplePlay
   ...

irq:
   pha
   txa
   pha
   tya
   pha
   bit $4015 ; ack irq
   lda #sample2
   jsr FamiToneSamplePlay
   pla
   tay
   pla
   tax
   pla
   rti

nmi:
   ...
   jsr FamiToneUpdate
   ...
   rti

The sample1 plays fine but sample2 don't.
I'm doing something wrong, there's another way to achieve this?
Thanks in advance.
Re: Play 2 DMC samples in sequence
by on (#236601)
1. You need to store more than just A. FamiToneSamplePlay will clobber X as well. Not sure about Y... I'd save it by default anyway.

2. Reading $4015 does not clear the DPCM IRQ flag. Writing it does. Not sure if that matters because FamiToneSamplePlay should write it anyway,

Also, when the DPCM IRQ fires there are still 8 samples left to play (it fires when the last byte is read, but it still continues playing one more byte afterward), so there is some breathing room there.

The main thing I'd suggest for now is just make sure your IRQ is getting hit. Put a breakpoint on it and ensure that's happening before you try debugging your IRQ routine. There are a number of things that could prevent the IRQ from happening (e.g. if the first sample is set as looped, it won't create an IRQ).
Re: Play 2 DMC samples in sequence
by on (#236602)
DMC IRQs are enabled by the upper bit of register 4010, in famitone called APU_DMC_FREQ

in the famitone2.s, below _FT2SamplePlay, it does

lda (FT_TEMP_PTR),y ;pitch and loop
sta APU_DMC_FREQ

you should set that bit with...

lda (FT_TEMP_PTR),y ;pitch and loop
ora #$80
sta APU_DMC_FREQ

and at the end of your IRQ code put a SEI, so that you don't have IRQs repeatedly firing (from the end of the second sample)
Re: Play 2 DMC samples in sequence
by on (#236605)
@dougeff After editing the famitone code as you suggested the IRQ was fired, but it's called in loop.
My IRQ routine looks like this now:

Code:
irq:
   pha
   txa
   pha
   tya
   pha
   lda #sample2
   jsr FamiToneSamplePlay
   sei ; <--- it's supposed to disable irq firing, but don't !!
   pla
   tay
   pla
   tax
   pla
   rti
Re: Play 2 DMC samples in sequence
by on (#236606)
RTI restores the status of the IRQ disable flag to whatever it was before the IRQ handler started; you must disable the IRQ in a different way than SEI.
Re: Play 2 DMC samples in sequence
by on (#236607)
lidnariq wrote:
RTI restores the status of the IRQ disable flag to whatever it was before the IRQ handler started; you must disable the IRQ in a different way than SEI.

This is the reason why I initially was doing
Code:
bit $4015
as @Bregalad pointed out in this thread
Any suggestion?
Re: Play 2 DMC samples in sequence
by on (#236608)
I don't know, let me think

find the byte in the sample definition that loads to the 4010, here's an example...

.byte $00+.lobyte(FT_DPCM_PTR),$36,$0f

the $0f is that byte (yours might differ, depending on sample rate)

Change it to $8f just for the first sample.

then remove that
ora #$80
line that I mentioned earlier.
Re: Play 2 DMC samples in sequence
by on (#236609)
Found the answer here
"Upon generation of a IRQ, to let the DMC know that the software has acknowledged the /IRQ (and to reset the DMC's internal IRQ flag), any write out to $4015 will reset the flag, or a write out to $4010 with the MSB set to 0 will do. These practices should be performed inside the IRQ handler routine. To replay the same sample that just finished, all you need to do is just write a 1 out to bit 4 of $4015."

my IRQ handler:
Code:
irq:
   pha
   txa
   pha
   tya
   pha
   lda #sample2
   jsr FamiToneSamplePlay
   lda #$0f
   sta $4010 <-- play sample2 and ack irq
   pla
   tay
   pla
   tax
   pla
   rti


dougeff wrote:
find the byte in the sample definition that loads to the 4010, here's an example...

.byte $00+.lobyte(FT_DPCM_PTR),$36,$0f

the $0f is that byte (yours might differ, depending on sample rate)

Change it to $8f just for the first sample.

then remove that
ora #$80
line that I mentioned earlier.

I'll try it later to avoid messing with the famitone code :wink:

Thank you all!
Re: Play 2 DMC samples in sequence
by on (#236610)
@dougeff worked like a charm!
Thank you again.

EDIT:
I forgot to mention that it's works only to trigger the IRQ but to acknowledge, a write of %00xx1111 to $4010 is still necessary.
Re: Play 2 DMC samples in sequence
by on (#236613)
Doesn't the $4017 IRQ inhibit bit affect this also? If so, it may be working because of the default/power-up state. Best to set it explicitly, or it could come back to haunt you.
Re: Play 2 DMC samples in sequence
by on (#236642)
Memblers wrote:
Doesn't the $4017 IRQ inhibit bit affect this also? If so, it may be working because of the default/power-up state. Best to set it explicitly, or it could come back to haunt you.

Makes sense...but how?
This way?
Code:
lda $4017
ora #%01000000 ; set bit 6 to disable the IRQ inhibit flag
sta $4017


And when? Once at startup or after a write to $4010?
Re: Play 2 DMC samples in sequence
by on (#236677)
NOOPr wrote:
Memblers wrote:
Doesn't the $4017 IRQ inhibit bit affect this also? If so, it may be working because of the default/power-up state. Best to set it explicitly, or it could come back to haunt you.

Makes sense...but how?
This way?
Code:
lda $4017
ora #%01000000 ; set bit 6 to disable the IRQ inhibit flag
sta $4017


And when? Once at startup or after a write to $4010?


In that case you should do LDA #$40 instead, as reading $4017 won't provide anything useful. And just once at startup is enough.