From the new NSF export available in Deflemask, it looks like Delek found a very interesting technique for doing PCM in NSF. I hope he doesn't mind me sharing. It's not open source, but it's pretty easy to deduce from a debugger:
During INIT:
1. SEI
2. Write $00 to $4017
Non returning PLAY:
1. SEI
2. PCM playback loop with a poll of $4015 after every loop.
3. If $4015 bit 6 is set, do your regular music update, then return to loop.
I was surprised to find that many NSF players, including the PowerPak, support this. There are a number of players, however, which do not really support this feature of the frame counter (NSFPlay included, though I've been meaning to rewrite its frame counter).
Anyhow, this is pretty interesting. It seems a lot more viable than the non-returning INIT hack supported by foo_gep. Obviously it's got a few support problems (use of SEI is bit of a red flag to me), but I thought it was pretty cool that it works with a lot of NSF player implementations. Also, from what I remember reading, $4015 will fail to clear bit 6 if you read on the same cycle it's set? Maybe you'll get a double frame now and then.
During INIT:
1. SEI
2. Write $00 to $4017
Non returning PLAY:
1. SEI
2. PCM playback loop with a poll of $4015 after every loop.
3. If $4015 bit 6 is set, do your regular music update, then return to loop.
I was surprised to find that many NSF players, including the PowerPak, support this. There are a number of players, however, which do not really support this feature of the frame counter (NSFPlay included, though I've been meaning to rewrite its frame counter).
Anyhow, this is pretty interesting. It seems a lot more viable than the non-returning INIT hack supported by foo_gep. Obviously it's got a few support problems (use of SEI is bit of a red flag to me), but I thought it was pretty cool that it works with a lot of NSF player implementations. Also, from what I remember reading, $4015 will fail to clear bit 6 if you read on the same cycle it's set? Maybe you'll get a double frame now and then.