Okay, I've used Famitracker, and I think that it is way awesome. I like being able to use the mouse now. I think DOS sucks. But anyways, I was wondering how you actually include this in a game. Do you make it a .BIN or .NSF extension? And where are the load/init/play addresses, and how do you know? Like the example famitracker file, where would those addresses be in that? Thanks for anybody that answers my question. =)
Okay, I don't mean to sound retarded. But I am just wondering how you know where the load/init/play addresses in the NSF file are. It shows you the "music data address" and that is all. But what does that mean? How do you know where to find the important adresses?
Celius wrote:
Okay, I don't mean to sound retarded. But I am just wondering how you know where the load/init/play addresses in the NSF file are.
According to the
.nsf spec, a .nsf file consists of a 128-byte header segment (which is not loaded into NES CPU address space) followed by several 4096-byte PRG ROM segments (which are).
The load, init, and play addresses are located in header at $08, $0A, and $0C respectively and refer to CPU addresses in $8000 through $FFFF. The bytes from $70 through $78 control which PRG ROM segments get loaded into CPU space at load time, but I don't understand how they interact with bankswitching.
Okay, I guess I didn't know that one before... I didn't know that the addresses were in the header before. But okay, those addresses are also what I am confused about. What address are they referring to? Like in the NES program, in the NSF file itself, what? I'm just confused about that. So if an NSF is incbined at $8000 in a NES program, and the init adress is $8000, or so it says in the header, where would you actually jump to? And should the header be removed before being put into the ROM? Sorry, NSF files have always been my feild that lacks knowledge in NESdev.
The addresses are in NES's space. So yeah, it'd be $8000. And you do have to remove the NSF headers normally (unless you .incbin at the load address minus 128, which is impossible if the address is $8000).
Here's some directions for how to use music in a game. (I'll write a tutorial sometime.)
1. Grab the music driver code from the webpage. (Written for CC65's assembler.)
2. You must choose a memory location where you want to place the music data. (There must be enough free space, try creating a NSF to see how much is needed.)
Then fill the 'music data address'-field with that location and press the 'Write BIN'-button to create a music data file.
3. Tell the driver the same address (the SONG_OFFSET constant).
Include the driver (may be anywhere) and the music code (at your chosen address) into your code. Call 'sound_init' to initialize the driver, and then periodically call 'sound_driver' to play the music.
I don't think anyone have used this in a program before, so I'd like to hear what you think. (If there's anything you want to change or something).
I'm a little confused about what you are telling me to do. I think you should make an option on FamiTracker to make an NSF that'll be already totally usable by a NES ROM. So just make an option that's like: "Make Usable" and it'll make an NSF that will have no header, and the NSF maker will tell you the addresses of init/play/load addresses of the songs, so you can just throw it into a rom with this code:
Code:
.inesprg 1
.ineschr 0
.inesmir 0
.inesmap 0
.zp
LowVar: .ds 1
HighVar: .ds 1
.code
.bank 1
.org $FFFA
.dw nmi
.dw reset
.dw irq
init = $8xxx
play = $8xxx
load = $8xxx
.bank 0
.org $8000
.incbin "example.nsf"
reset:
lda #%00011111
sta $4015
lda #1 ; song 0
ldx #1 ; NTSC speed
jsr init
lda #%10000000
sta $2000 ; <- enable play after init
loop:
jmp loop
nmi:
jsr play
irq:
rti
And you'll be all ready to go. I don't know. I've always hated NSF files, they're nothing but trouble to me. I've never in my life successfully put an NSF that I've made into a NES ROM. So if you could make it as simple as possible for me, that'd be really cool of you
. I can do a whole ton of other crap in 6502, I'm not a newbie, I know what I'm doing, but I really don't understand NSFs at all, or why mine don't work.
Heh, I'm going to change it anyway. Like, right now you have to split the bin-file manually if DPCM-samples are used (or else a lot of space is wasted).
Using nesasm makes things a bit more complicated, but it's still possible to assemble the music driver separately and then merge the files.
The easiest way to get an NSF running (that's made in famitracker):
remove the header (first 128 bytes), load the file at $8000 and call $8000 to init the song and $8003 to play it.
This code works, just remove the first 128 bytes from the NSF.
Code:
.inesprg 1
.ineschr 0
.inesmir 0
.inesmap 0
.code
.bank 1
.org $FFFA
.dw nmi
.dw reset
.dw irq
.bank 0
.org $8000 ; NSF load
.incbin "example.nsf"
reset:
lda #%00011111
sta $4015
lda #$00 ; song 0
ldx #$00 ; NTSC speed
jsr $8000 ; NSF init
lda #%10000000
sta $2000 ; <- enable play after init
loop:
jmp loop
nmi:
jsr $8003 ; NSF play
irq:
rti
But of course, the problem with using a lot of these general-purpose music formats in a game is data size. I saw this comment in the playback code:
Quote:
To do:
Compress pattern-zeroes (there would be lot of space to save)
How many typical NES style songs can one fit in a 16 KB bank of UNROM or S*ROM?
Quote:
How many typical NES style songs can one fit in a 16 KB bank of UNROM or S*ROM?
The driver is 3.4 kB, and a typical NES song (my enl_end.nsf in this case) uses about 3 kB (DPCM samples excluded).
I don't think the music format is a big problem.
The driver would need some optimizations though, but mostly to decrease the CPU usage. I haven't really focused that much on the driver this far, as the goal has been getting the tracker usable, but it's probably time for that now.
(Everything is open source, contributions are welcome)
The NT2 driver is about the same size, but its sequence files are a lot smaller.
I have a question. How do you make the tracker wrap around to keep looping a certain section? Like if I want the first 2 sections to be played in the beggining, but have the rest of the song keep looping and never play the first 2 sections again, how would I do that? I know in NT2, you have to press space over the section that you want the song to go to when the song reaches the end, but how is this done in FamiTracker?
tepples: By compressing unused notes the song was cutted by 1 kb. I'm going to put some more work in optimization.
Celius: You want to use the jump command Bxx, where xx is the new frame (02 for frame 2).
Okay, now for my next question. How do you put more than 1 track in an NSF with famitracker?
Celius wrote:
Okay, now for my next question. How do you put more than 1 track in an NSF with famitracker?
There is no easy way right now, but you can modify the playback code to load music from different addresses depending on the x register in the init routine.
I'll add real support for multitrack files some time.