NSF player, like Loopy's?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
NSF player, like Loopy's?
by on (#52150)
Hey guys -
I am trying to write something similar to Loopy's NSF playback rom. For my purposes I need to have 2 Nintendos going at once, both running an NSF. Instead of buying a second powerPak, I am looking to just burn EPROM carts. However, I don't know how to use Loopy's player Rom outside of the PowerPak environment (is it even possible?)

So I'm trying to write one myself. I would need to re-compile and burn a new chip for every song I do, but this is ok. I was able to get alot done musically with just a handful of chips this year.

I got my first NSF player to work using an old thread here. I have combined that with some joy-handler routines I had in NBasic. I'm starting by trying to get the song to reset on a button-push. I don't know much about the NSF format, how to work with it, I just tried jumping to the init address when I pushed left. This didn't work, it just stopped the song. I think there's alot more going on that I need to take into account.
How do I get the NSF to start over, or move to another song?
Any help would be greatly appreciated - I am spending alot of time on this problem. I can throw the code out here but it's super-simple at this point.

by on (#52154)
You need to make an NMI routine, and have the NSF Play routine called from there. Use JSR, rather than JMP.

For the init routine, load the song # into A and JSR to the init routine. Some players will use the X or Y register to select NTSC or PAL. After that point you can enable NMI, then do whatever in your main loop while the play routine runs automatically. You need to disable NMI or otherwise stop playing when you change tracks.

With 2 Nintendos you could take 2 NES controller cables, link them and cross-wire the D0 and strobe/latch lines for communication. That'd be a fancy way to make it sync up, but with the right software in place, you wouldn't have to change the EPROM. That would require a custom sound engine though.

by on (#52225)
Cool, thanks! I had no idea to disable the NMI when I changed tracks/restarted, I think that is why it wasn't working. I'll try it out...

I was looking for a really nasty, simple syncing solution (though I'm interested in more software-oriented ones for the future, and possibly using a MidiBox hardware platform, arduino or midifi kit to get a solid clock pulse out of the 2A03?).

Would it work to just wire an NES controller to go to the Player 1 slots for both units? So, pressing start on 1 makes the song restart on both.

In my head I have seperate controllers for both, as well, so I could switch patterns arhythmically, and then use the "master controller" to slam the sync in place. So each NES would have 1 dedicated controller, and then a third controller would be split to go into both units. Sketchy I know...I'm doing sort of DPCM breakcore/gabber/punk. Manual syncing midiNES with a free-playing NSF works ok, but I miss beats.

by on (#52229)
You could hook one controller to 2 NES's, but you will need to add a 2nd CD4021 chip in there. If there's enough room, ideally it could piggy-back on top of the original to simplify the connections. For the 2nd chip, then you would bend up the pins used for clk and data, which would go only to the 2nd cable.

by on (#52244)
Ok, rad, thanks for the help on the hardware portion. I'll see how far I can get with that this weekend, and just test it out by playing mario in "stereo" or something, hah.

I got the track restart to work in the NSF player - on the "Left_Button_Press" routine, I am JSR'ing to the init address, setting $2000 to 10000000, and then JSR'ing to the init address again. I tried different combinations of writing to $2000 to disable the NMI, and then JSR'ing to the init address, and this is what ended up working, heh.

As I was experimenting with different NSFs, I found that the same program would not work if there was DPCM samples in the NSF. When I export the track to NSF from famitracker, I noticed it tells me that the sample location is $C000. That was the initial .org address of the player code, so I tried changing the .org at the top to $8000, but still no dice. Any ideas? The player code is essentially given here (at the bottom, Banshaku's post):

http://nesdev.com/bbs/viewtopi ... =nullsleep

Anyway, crap, thanks for helping/carrying me on with this, it's gonna shred!!

by on (#52254)
Better try changing the NMI routine to this:

Code:
NMI_Routine:
 pha
 tya
 pha
 txa
 pha

 jsr nsf_play
 
 pla
 tax
 pla
 tay
 pla
 rti


With there being code in the main loop outside of NMI (polling controller and such), then the NMI will need to save/restore the register state or there could be total chaos. It's pretty lucky that it works at all! I guess that running the init routine twice is just increasing it's odds of success.

If you moved the code to start at $8000, and tested in an emulator, have you changed the iNES header to specify 2 banks? This could also affect the PowerPak loading. Also since you're using NESASM, there's the whole issue of using the .bank command, have you handled that as well? Also, NESASM won't let you include any file larger than 8kB - another potential problem.

Usually the quickest way to test if a ROM is totally screwed up or not, is to load it in an emulator, go into the debugger (single-step mode), pause it, then reset and see where it starts out.