DMC IRQs

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

Well can't you play the shortest 1-byte sample at rate $0f for the initial tuning, then play a longer/slower sample for a second IRQ, then wait a variable time that adds up to a constant with the first delay ? I'm pretty sure you could.
Of course if you play a slower sample you loose resolution, but then you'd have to find the best length/rate ratio for this. Then it'd be a tradeoff between playing a longer sample, thrus waste ROM, or play a shorter one and waste some CPU time counting useless IRQs before the interesting one.
Useless, lumbering half-wits don't scare us.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

IIRC, the whole problem with DMC IRQs is that the APU runs at it's own pace, meaning that even if you give it the command to start playing a sample at the same point in the frame every time, the IRQ will not happen at the same time.

If we count how long it takes for the IRQ to fire (this is one of the waiting loops), we know what the error is, and we can use this information to compensate for the error later (this is the second waiting loop), when it's time for the raster effect.

Maybe it is actually possible to detect the error using a shorter/faster sample to reduce the amount of waiting, but it might not be trivial to dynamically vary the frequency during the frame as the split point comes closer.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

No, no that's not what I mean.

The timing diagram of what I mean is that :

Code: Select all

------------------
NMI Vblank sync
Sprite DMA, VRAM updates, etc... (constant time)
------------------
start playback of short sample (varying time)
enter in a loop polling $4015 and counting iterations
--------------------
"IRQ #1" -> count time before the pseudo-IRQ (an actual IRQ isn't needed and can be disabled with SEI, this is automatically done in an NMI routine by the way).
Start playback of long/slow sample (fixed time)
RTI (also clears the I flag)


....sound, game engine, etc. code here....

-------------------
IRQ #2 -> disable DMC channel
Wait for constant time minus the calulated one
Wait for an adjustement time for the raster effect (compensate for lack of precision in lenght/speed of the long sample)
Raster effect register writes
RTI
----------------------

end of frame here
----------------------
I think this is what would make the most sense to me, and I think it should work, but the adjustment time that compensate the lack of precision must not be too big else too much CPU time will be wasted
Useless, lumbering half-wits don't scare us.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Bregalad wrote:Well can't you play the shortest 1-byte sample at rate $0f for the initial tuning, then play a longer/slower sample for a second IRQ, then wait a variable time that adds up to a constant with the first delay ?
I already do this, sort of: I use a 1-byte sample and a 17-byte sample. The 1-byte sample takes 1*8*54 = 432 CPU cycles, or 432*3/341 = 3.8 scanlines. The 17-byte sample takes 17*8*54 = 7344 CPU cycles, or 7344*3/341 = 64.6 scanlines. I already do play a 17-byte sample to skip large areas. But there's nothing in between a 1- and 17-byte sample. On the other hand, you're right that I haven't investigated playing the 1-byte sample at maximum rate (54 cycle period) and then switching to 1-byte samples at a slower rate (longer period) in order to skip areas smaller than 64 scanlines.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

OK I took time to compute the # of scanline each possibility of DMC length, for both NTSC and PAL (hopefully I didn't do accidental errors).
I rounded all values to the higer integer, because if you want to wait N scanlines, you want the IRQ to happen BEFORE the Nth scanline after setting up the IRQ.
(samples taking longer than a frame are represented by stars)

Code: Select all

NTSC               Rate
Length              $0    $1   $2   $3   $4   $5   $6   $7   $8   $9   $a   $b   $c   $d   $e   $f
----------------------------------------------------------------------------------------------------
1-byte (8 bits)     31    27   24   23   21   18   16   16   14   12   10   10   8    6    6    4
17-byte (136 bits)  **    **   **   **   **   **   **   **   228  192  170  154  127  101  87   65
33-byte (264 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   196  168  126
49-byte (392 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   **   **   187

PAL                Rate
Length              $0    $1   $2   $3   $4   $5   $6   $7   $8   $9   $a   $b   $c   $d   $e   $f
----------------------------------------------------------------------------------------------------
1-byte (8 bits)     30    27   24   23   21   18   16   15   14   12   10   9    8    6    5    4
17-byte (136 bits)  **    **   **   **   **   **   **   **   225  189  169  151  126  100  85   64
33-byte (264 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   194  164  124
49-byte (392 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   **   **   184
Because a PAL interrupt will always happen about the same time or a bit sooner than a NTSC interrupt, I will use the NTSC table exclusively to set the "best" setting here :

Code: Select all

Delta      Best opt. for IRQ

1-3        Timed code
4-5        Length $0, rate $f
6-7        Lenght $0, rate $d
8-9        Length $0, rate $c
10-11      Length $0, rate $a
12-13      Length $0, rate $9
14-15      Length $0, rate $8
16-17      Length $0, rate $6
18-20      Length $0, rate $5
21-22      Length $0, rate $4
23         Lenght $0, rate $3
24-26      Length $0, rate $2
27-30      Length $0, rate $1
31-64      Length $0, rate $0
65-86      Length $1, rate $f
87-100     Length $1, rate $e
101-125    Lenght $1, rate $d
126        Lenght $2, rate $f
127-153    Length $1, rate $c
154-167    Lenght $1, rate $b
168-169    Lenght $2, rate $e
170-186    Length $1, rate $a
187-191    Length $3, rate $f
192-195    Length $1, rate $9
196-227    Length $2, rate $d
228-239    Length $1, rate $8
Therefore, after counting a necesarly initial wait of 4 scanlines, which is necessarily for the sync because of how DMC works, you should compute the # of scanline that remains to wait before the split and use the lockup table above.

Note that it's in most cases unnecessary to have a sample longer than 17 bytes, because it will only save a couple of scan-lines in the final fine-tuned timed code wait. The only exeption is if you want to wait something close to 220- 227 scanlines, where there is a significant gap where it's best to use a 33 bytes sample.

Also note the huge gap between 31 and 64 scan lines, where there is nothing better than 31 scanlines available. If you wanted to wait, let's say exactly 63 scanlines and use only one IRQ, you'd have to set an IRQ to line 31 and wait the remaining 32 lines "by hand", wasting a lot of CPU usage. Therefore for this game I'd really to use a second IRQ, to save CPU usage.

So there is probably no way more than 2 IRQs and more than 8 scanlines of "timed code" would ever be required for this, for ANY split.

I agree it's not the most amazing thing in the world, but remember all this is possible WITHOUT ANY MAPPER.
Useless, lumbering half-wits don't scare us.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

This is a very interesting idea, Bregalad. Suddenly I feel very tempted to try coding the "definitive mapperless scanline counter" again...! =)
Post Reply