Help with NSF ripping

Ugly Joe

New member
I'm trying to rip the music from "Tetris 2 + BomBliss", but I've never done it before and I've hit a snag. I'm using the "NES Music Ripping Guide" by Chris Covell as a guide. I've found the sound data itself already, and I'm pretty sure that that play address is 0x8000. I have a couple guesses for the init address, but I don't know. My real question is, what is the load address? The guide doesn't clearly define what it actually is and I don't want to try brute forcing the init address (by trying all addresses following an RTS) if I don't have this one right first. So, what is the load address?

Also, how common is bankswitching in nsfs? This is the other thing that I think might be my problem (though I haven't read up on it at all...).

<P ID="signature"></P>
 
> My real question is, what is the load address?

It's where to begin placing the NSF code. All the data following offset 0x00080 in the NSF file will be put in PRG-ROM by the NSF player -- where in PRG-ROM it goes is dictated by the load address. If the load address is $8000, the first data byte in the NSF will be placed at $8000. If it's $C000, the first data byte in the NSF will be placed at $C000

Bankswapping NSFs work a little different -- the load address (AND 0x0FFF) is how many bytes to leave empty in the first bank. The order in which the banks are swapped into PRG is determined by the bankswapping bytes in the header.

I don't really know how common bankswapping is -- but in smaller ROMs it probably isn't necessary. Games would typically try to keep it all in the same bank unless there's too much data to crap into one bank (large soundtracks like FF3 probably have this problem).

I also feel compelled to recommend my NSF player/tracer for debugging your NSFs: http://disch.zophar.net/slicknsf.phpSlickNSF</a>. It's strict (so the rip is forced to be proper or it won't play) and has a nice tracer to aid debugging.


Although unfortunatly, I have no experience in actually ripping NSFs, so I can't give you pointers or anything.

<P ID="signature"></P>
 
Most NSF's have a load address at $8000 and if all the music code is in a 32K section of program rom then the load should be $8000 in an unoptimized rip.

I usually set a write breakpoint to $4000 - $4009 in Nesten and dump the upper 32K which is $8000 - $FFFF, Usually this is the entire music code and data.

Nintendo music drivers can be difficult to rip sometimes because there is no specific init address. You have a specific memory address usually in the zero page area that defines the tune number and when the contents of this address is changed and then the player code is updated for the change in tune. Most of the older nintendo drivers start with the play code writing FF to 4017 and 0F to 4015. and at the end of the play code writes 00 to a few addresses and these are usually the tune addresses. You can deduce what these addresses are by using a memory viewer such as VirtuaNES or FCEU(not the debug version).

Some Nintendo tunes have a different format such as having a specific init address and you can sometimes find these by the usual way of tracking writes to 4015 and looking at the stack to trace backwards. I've also noticed that you need to make a boot strap code so what you do is locate where in the reset code the sound regesters are being written to and its usually a sub routine.
save Accumulator first and then JSR to the routine and then pull the accumular back.
PHA
JSR $nnnn
PLA
JMP $init
.
As far as bankswitching is concerned you need to be familiar with the mapper that the game uses and track the music code and see if the banks are switched when and if the data and/or init code is on another bank. You can use FCEUD if you want to track the code. If you want to use a trace logger then use Nintendulator. Also FCEU is good for dumping smaller pieces of memory and is usefull in getting all the banks you need. Setting the NSF for play can be difficult and so you have to make sure the new bankswitching routines switch 4K banks instead of 32K,16K,or 8K banks. You need to set in the header what banks are going to be first loaded and then you have to switch the rest in via the NSF bankswitching regs. read the spec for more details.

Any more questions then let me know.

<P ID="signature"></P>
 
I don't have a internet connection at home so I got at home and found the rom and what do you know the rom was programmed by BPS. Normally BPS has crappy music, this music was composed by Koichi Sugiyama and so is good.

This music driver is all on one bank and is not bankswitching. All within $8000 - $BFFF. This rom is MMC1 I do believe and so the framework of the rom will be the hardwired section of the PRG located at $C000 - $FFFF. You will find both init and play addresses in this section. The play address that you have is right and is $8000 called from in the NMI as usual. However you won't find the entry to the init by the normal means of searching for writes to $4015. The entry to the init is located indirectly. You will find code in the zero page section of the WRAM. So make a address break point for $0023 and you will find the init address, make sure that you maike the break before the music plays as the routine is also used by the BRK interrupt and a couple of other things. Also you will find the pointers for this address at $8005 - $8006 I think. I don't have the rom right here. Just switch the bytes arround and that's your address.

Arrange the tunes and enjoy.

<P ID="signature"></P>
 
> Normally BPS has crappy music, this music
> was composed by Koichi Sugiyama and so is good.

Ah, I thought that they had a familiar sound to them.

> This music driver is all on one bank and is not
> bankswitching. All within $8000 - $BFFF.

Hooray! I got that part right.

> The
> play address that you have is right and is $8000 called from
> in the NMI as usual.

Hooray again!

> So make a address
> break point for $0023 and you will find the init address,
> ...
> address at $8005 - $8006 I think.

I did that, but didn't find the right address at $8005-$8006. I just watched the JMP at $0023 change in fceuxd and wrote down the addresses 'till I started seeing duplicates. Then I tried them each in the NSF header until it worked.

> Arrange the tunes and enjoy.

Will do! Thanks for the help (and thanks to Disch, too!)!

<P ID="signature"></P>
 
Finished!

Okay, I finally got it.

The arrangement was more annoying than expected. I added the function to do it, but my first try overwrote the DPCM sample used in the first track. Not very lucky.

I found another place for the function and placed it there instead. It worked this time, but the first track would crash after trying to play the DPCM sample. After trying a couple of things, I realized that, after playing the DPCM sample, it was jumping back to the init point, which then ran the arrangement function (offsetting the accumulator), and then tried to play a song that didn't exist.

So, I changed the init address in the header to the arrangement function and had that jump back to the real init address when it was done. This actually seems to make a lot more sense than the method in "NES Music Ripping Guide".

I'm pretty sure only the first track (the title screen music) uses DPCM samples. All of the tracks sound fine to me, so I'm pretty sure this is complete. The only other thing I can think to add is the sound effects, but I have no idea where those are <img src=smilies/magbiggrin.gif>

<P ID="signature"></P>

C:ServerxampphtdocszopharoldwwwthreadsattachmentsTetris2BomBliss.zip
 
The address I specified at $8005 - $8006 is data pointers. You won't access this data unless you do a read breakpoint in a debugger. If you take the data in these two addresses and swap them arround then that's your init address because the indirect routine accesses these data bytes.

I'm glad you got it to work and yes the music is nice, I enjoyed it myself.
 
Re: Finished!

Nice job. This has never been ripped before? This 1st track is crazy the way it goes... well... crazy then loops. I have never played Tetris 2 on the NES so I don't know if that is not supose to be there. If not I think it goes with the song.
 
Re: Finished!

> Nice job.

Thanks.

> This has never been ripped before?

It hadn't been ripped yet as far as I can tell. It's by the same composer of the Dragon Quest/Warrior music, though. One or two of the tracks sounded very familiar to me, so there may be some overlap into some of the Dragon Quest soundtracks.

> This 1st
> track is crazy the way it goes... well... crazy then loops.

The first track has that bomb explosion noise right before the loop. That's how it was in the emulator, so that's how I kept it. The game is called Bombliss, afterall <img src=smilies/magbiggrin.gif>

> I have never played Tetris 2 on the NES so I don't know if
> that is not supose to be there. If not I think it goes with
> the song.

Well, I doubt it's on the US Tetris 2.

JP => US
Tetris Flash => Tetris 2
Tetris 2 + Bombliss => Tetris Blast (gb)

It's a great game. I loved Tetris Blast, which this has and then some, and it also has the original Tetris modes plus one more (with junk rising up from the bottom). It even has multiple player slots and sram saves for your high scores and custom puzzles. I would love to have this in cart form.

btw, whoever maintains ZD's nsf archive can feel free to add this.
 
I think my sentiments could best be summed up with a roflcopter:
roflcopter2.gif
 
> ugly joe, why do you kiss the ass of swampgas?

WTF?<img src=smilies/eek13.gif>... WTF?!?!?!?!?!?!?! What the hell does this have to do with NSF anything?
 
Back
Top Bottom