Playing an NSF in-game

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Playing an NSF in-game
by on (#17363)
Hey all.

I started trying to get a song to play from my nsf. I'm obviously doing something wrong since the song won't play. Here's some snips of what I have:

Code:
.org $c000

thesong:
.incbin "sleuth.nsf"
   rts

... ; vblank, RAM clear, etc.

   jsr sound

... ; code

sound:
   lda #%00011111
   sta $4015
   rts

song1:
   lda #$0
   ldx #$0
   jsr thesong
   lda #%10000000
   sta $2000
   jsr sound
   rts

... ; more code

vblank:  ; Actually is NMI, but I'm following NES101 and he called it Vblank :P
   jsr controller
   jsr sound


When I boot it up in Nintendulator, you can hear the speakers kick on from initializing the sound... but then no music. I'm not quite sure what is wrong. If anyone could help me out as to what I'm doing wrong, I'd appreciate it.

by on (#17384)
This almost seems like a joke. You're joking, right?

So you incbin'ed an NSF and then JSR to it... Taking a look at the header of the NSF shows "NESMxxxxx" which the NES interprets as code and eventually runs into a BRK instruction.

Since I love NSFs and NES music, I'll help you out:

First, look at the header of the NSF, using a hex editor. Write down the bytes stored from 0x08-0x0D in the file. Those are the load address, init address, and play address, respectively (stored in 6502/Intel byte order). Then, using the same hex editor, remove the 128-byte header of the NSF, and save the remaining binary file in the same directory as your ASM code.

Incbin THAT binary file with the same origin ORG... as what the load address was of the NSF. You may have to put your own ASM code at a different location so the music code does not write overtop of it.

In your ASM code, set up two EQUs (constants, whatever) INIT_ADDR, and PLAY_ADDR and set those to the addresses you got from the NSF bytes 0x0A,0x0B and 0x0C,0x0D. Be sure to write it the right way, eg: INIT_ADD EQU $8000

In your ASM code when you set up RAM, etc, you type this in:
Code:
lda #$01   ;or whatever number song you want
jsr INIT_ADDR


and inside your NMI/Vblank routine, you simply do this:
Code:
jsr PLAY_ADDR


There's usually no need for you to set $4015 or anything. Just make sure your ASM code's RAM use doesn't conflict with the NSF's RAM use.

by on (#17387)
ccovell wrote:
This almost seems like a joke. You're joking, right?


Nope, not joking at all. Very new to this :)

Thanks for your post though. It's running now. I didn't understand how to implement it to play with through reading the header and using it's info without some assistance over AIM... it took a LONG time too. The post you made will be good for any others that may not understand. Thanks.

by on (#17556)
Roth wrote:
The post you made will be good for any others that may not understand. Thanks.


Yep, thanks for that info!

NC

by on (#36726)
spamming(to track the topic later) :D