Page 1 of 2

In NSF, how to start track from loop point without delay?

Posted: Fri Nov 19, 2010 7:23 pm
by Exploding Rabbit
Hi. I'm the creator of the game Super Mario Bros. Crossover. It's a flash game that recreates Super Mario Bros and allows you to play as other characters. In the last release, I incorporated an NSF player (Game Music Emu) into the game so that I could have a lot of music with a small file size.

However, the main problem I have with NSF is that I cannot change the start time of the track. If I use the seek function, the game comes to a complete hault while it seeks to the point in the song I need. The way I understand it, it's not possible to move to a different point in a song without emulating the entire song up to that point. Is this true? Is there any way around it?

The solution I have come up with is to create custom NSF files that would have additional tracks which are duplicates of the original song but that start from the time I need them to start at. I have come here asking if this is possible and how difficult it would be to do.

I wouldn't need a lot of these custom NSF's... at least not right now. The main ones I need are one song in Mega Man 3 and one song in Blaster Master. I need to be able to start the songs from the loop point instead of the beginning of the track. Any info you guys can give would be greatly appreciated. Thanks!

Posted: Fri Nov 19, 2010 7:36 pm
by Dwedit
Welcome, exploding rabbit! Super Mario Bros. Crossover is an awesome flash game.

Since NSF files are basically roms, and NSF players are basically emulators, I think the answer for faster seeking is savestates. You'll need to create savestates for each point you want to start the music from, but that requries the NSF player to support save states.

Another way is to asm-hack the NSF so it starts with a particular initial state (RAM, sound, and CPU registers), so any NSF player will work, whether or not it has savestate support. It's like embedding a savestate into an NSF file.

Posted: Fri Nov 19, 2010 8:38 pm
by Dwedit
Example of a hacked NSF file (Mega Man 3, plays the ending music as the first track)
Download

To make the RAM dump, I'm using the emulator FCEUX, hitting Pause and Frame Advance to get to the right frame, then in the Hex Editor (Debug -> Hex Editor), I'm dumping the RAM (File -> Dump to File -> Ram).

I made an NSF shim that includes the original NSF, but overrides the Init address, then I load the copy the RAM dump into the NES's memory as the replacement Init code. Miraculously, that's enough to get it working.

Posted: Fri Nov 19, 2010 9:19 pm
by Exploding Rabbit
Hmm... I don't think Game Music Emu supports save states, so we'll have to use the second method. So when I dump the RAM from FCEUX, do I go to a part in the game that has the music playing at the exact part I need it to start at? I think usually when I go into frame advance mode, the sound stops playing so it would be hard to tell.
Dwedit wrote:I made an NSF shim that includes the original NSF, but overrides the Init address, then I load the copy the RAM dump into the NES's memory as the replacement Init code. Miraculously, that's enough to get it working.
I don't understand this part at all. Could you explain in a little more detail?

Also, if I do this, I'll basically be including two copies of the same NSF file, which uses up a lot of memory. Well, it's not a lot, but is there any way to have the hacked nsf file only have the song I need or does it have to be everything?

Specifically what I'm trying to do right now is have the music from the first level of Blaster Master start from the loop point instead of the 7 second intro. You can use that as an example to explain it if you want. Thanks so much!

Posted: Sat Nov 20, 2010 12:15 am
by Dwedit
Blaster Master

This one was harder, because it doesn't automatically write to all the sound registers given just a RAM state. Had to step through the code to figure out which bytes to change so it would write some of the sound registers, then had to add some ASM code to write to the rest.

Posted: Sat Nov 20, 2010 12:37 am
by Memblers
It might be worth changing the init address, to skip over the init routine added during the rip (and check all tracks 0-255). It's seemed kinda common to have separate tracks with and without intros, etc. But this type of stuff might be removed in the NSF rip as a duplicate.

Save states in an NSF, that's a pretty cool hack.

For an NSF optimizer, there actually was one but I can't find any trace of it online. It was by TNSe (who made NESten), called NSFTool. A google search turns up a much simpler NSF editor. You would set the time length, it would emulate it for that time, so you could zero-out any memory that wasn't used. When I made my SNES NSF player, this feature saved lots of memory and a huge deal of loading time. Too bad it seems to have vanished, or maybe it was never on a website (from 2001 or so).

Posted: Sat Nov 20, 2010 4:38 am
by Exploding Rabbit
Dwedit wrote:Blaster Master
Wow, thanks!!! This is EXACTLY what I needed. And it's all in one file too! The other song that causes the most trouble in the game is the first track in the Mega Man 3 NSF because the intro is so long. Can you make me a hacked Mega Man 3 NSF that has an additional track of that song starting at the loop point? Thanks again!

In the future there's going to be a lot of music in the game, and it'd be great to have versions of each track with the intro and without. Is this something that is difficult to learn or should I just come here and request custom NSFs? Also, I might switch to the NSFe file format later because I'll want players to be able to choose which songs to put in their own levels and I'd like to have the track name listed in the game. Will we have to remake the custom files if I switch? Will the process be different if it is NSFe?

You guys are awesome. I should have come here earlier.

Posted: Sat Nov 20, 2010 9:03 am
by Dwedit
The other way to optimize an NSF file is to make a tiny NES wrapper, and use FCEUX's Code/Data logger to create a stripped rom, then turn it back into an NSF file. Not only will all the other music data be missing, but much of the music code will be too.

Posted: Sat Nov 20, 2010 9:47 am
by tepples
Dwedit wrote:The other way to optimize an NSF file is to make a tiny NES wrapper, and use FCEUX's Code/Data logger to create a stripped rom, then turn it back into an NSF file. Not only will all the other music data be missing, but much of the music code will be too.
Great idea. Is there a tool that runs an NSF, logs it in such a manner, and zeroes out any unread ROM locations? If not, how hard would it be to make one, say by adding logging to Game_Music_Emu?

And how hard would it be to make an automated tool that uses such logging to make a cue sheet approximating the playing time for each track? A couple minutes after no new addresses have been read, you can assume the track has either ended or started to repeat.

Posted: Sat Nov 20, 2010 10:03 am
by Dwedit
Mega Man 3
This one plays the main part of the title song. I decided to start it AFTER one loop instead of immediately as the title song plays so it's cleaner.

I also included an example of a stripped NSF file, it's about 2k in size when zipped. It's missing maybe 15% of the music code, and has none of the music data except for the title loop.
When looking at filesizes, the only size that matters is how big it is after being GZIP-ed.

Posted: Sat Nov 20, 2010 2:30 pm
by Exploding Rabbit
Thanks again! That's exactly what I needed. Why does the file size only matter after being gzipped?

Posted: Sat Nov 20, 2010 2:54 pm
by blargg
Because if you care about file size, using gzip compression as a first step to reduction is cheap and easy. Why waste effort achieving what gzip can at very little cost?

Posted: Sat Nov 20, 2010 3:29 pm
by tepples
blargg wrote:Why waste effort achieving what gzip can at very little cost?
PowerPak can't gunzip.

Posted: Sat Nov 20, 2010 4:25 pm
by Exploding Rabbit
blargg wrote:Because if you care about file size, using gzip compression as a first step to reduction is cheap and easy. Why waste effort achieving what gzip can at very little cost?
Funny seeing you here... just kidding. I didn't think Game Music Emu could play zipped files.

Also, I noticed in the Blaster Master NSF that Dwedit made, it has more sounds than were in the original NSF. I even found some sounds that weren't used in the game. It's very helpful to have all the sounds from the whole game in an NSF because I sometimes play sound effects through NSF too. For example, in the Legend of Zelda NSF, it doesn't have the sound effect it plays when you find a secret. I try to use NSF to play sounds as much as possible because there's no quality loss and no addition to the filesize.

Posted: Sat Nov 20, 2010 4:27 pm
by Memblers
Hm, well if I can get ahold of TNSE sometime, maybe I can get his permission to upload NSFTool. I'm sure I still have it.

Exploding Rabbit: if you PM me your email address, I could send that app to you, if you think it would help. I forgot to mention in my other post too, that Super Mario Crossover is the best SMB hack / Flash game ever. :D

Yeah lots of extra tracks, sound effects, get removed by the ripper. If they didn't re-order it, the track order would be insane (lots of blank tracks inbetween, especially). When I was ripping NSFs I tried to keep the sound effects in it as much as possible, and even re-ordered those, but I'm sure other rippers aimed to remove them (since they just wanted the music I guess). Sometimes the sound effect routine is separate from the music routine, too.