NSF
The basic idea is one rips the music/sound code from an NES game and prepends a small header to the data.
A program of some form (6502/sound emulator) then takes the data and loads it into the proper place into the 6502's address space, then inits and plays the tune.
Header Overview
offset # of bytes Function ---------------------------- 0000 5 STRING "NESM",01Ah ; denotes an NES sound format file 0005 1 BYTE Version number (currently 01h) 0006 1 BYTE Total songs (1=1 song, 2=2 songs, etc) 0007 1 BYTE Starting song (1= 1st song, 2=2nd song, etc) 0008 2 WORD (lo/hi) load address of data (8000-FFFF) 000a 2 WORD (lo/hi) init address of data (8000-FFFF) 000c 2 WORD (lo/hi) play address of data (8000-FFFF) 000e 32 STRING The name of the song, null terminated 002e 32 STRING The artist, if known, null terminated 004e 32 STRING The Copyright holder, null terminated 006e 2 WORD (lo/hi) speed, in 1/1000000th sec ticks, NTSC (see text) 0070 8 BYTE Bankswitch Init Values (see text, and FDS section) 0078 2 WORD (lo/hi) speed, in 1/1000000th sec ticks, PAL (see text) 007a 1 BYTE PAL/NTSC bits, like NES 2.0 byte 12 bit 0: if clear, this is an NTSC tune bit 0: if set, this is a PAL tune bit 1: if set, this is a dual PAL/NTSC tune bits 2-7: not used. they *must* be 0 007b 1 BYTE Extra Sound Chip Support bit 0: if set, this song uses VRC6 audio bit 1: if set, this song uses VRC7 audio bit 2: if set, this song uses FDS audio bit 3: if set, this song uses MMC5 audio bit 4: if set, this song uses Namco 163 audio bit 5: if set, this song uses Sunsoft 5B audio bits 6,7: future expansion: they *must* be 0 007c 4 ---- 4 extra bytes for expansion (must be 00h) 0080 nnn ---- The music program/data follows
NSF is loosely based on the PSID file format for C64 music/sound.
Loading a tune into RAM
If file offsets $070 to $077 have $00 in them, then bank switching is not used. Data should be read from the file beginning at $080 and loaded contiguously into the 6502 address space beginning at the load address until the end of file is reached.
Bankswitching
If any of the bytes from $070 to $077 in the file header are nonzero then bank switching is used. In this case, take the logical AND of the load address with $0FFF, and the result specifies the number of bytes of padding at the start of the ROM image. The ROM image should consist of a contiguous set of 4k banks, read directly from the NSF file beginning at $080 after inserting the requested number of pad bytes. If the file does not have enough data to fill the last bank completely, it may be padded out.
The 6502's address space is divided into 8 4k bank switchable blocks. For each block the current bank is controlled by writing the bank number to at corresponding register at $5FF8 through $5FFF. The initial bank assignment is determined by bytes $070 through $077 in the file.
NSF Address Register ==== ========== ======== $070 $8000-8FFF $5FF8 $071 $9000-9FFF $5FF9 $072 $A000-AFFF $5FFA $073 $B000-BFFF $5FFB $074 $C000-CFFF $5FFC $075 $D000-DFFF $5FFD $076 $E000-EFFF $5FFE $077 $F000-FFFF $5FFF
The initial bank assignment should be done before any call to the init routine. Once the ROM image has been built from the NSF file, this can be set up simply by writing the 8 values from the file header $070-077 to the corresponding registers $5FF8-$5FFF.
If the init routine needs to change the bank assignments based on the selected song, it may do so by writing the bank control registers.
Example
METROID.NSF will be used for the following explanation.
The file is set up like so: (starting at $070 in the file) $070: 05 05 05 05 05 05 05 05 $078: 00 00 00 00 00 00 00 00 $080: ... music data goes here...
Since $070-$077 are something other than $00, this NSF is using bank switching. The load address given is $8000. The load address AND $0FFF specifies 0 bytes of padding, so we set up our ROM image with contiguous data starting from $080 in the file.
This NSF has 6 4k banks in it, numbered 0 through 5. It specifies that each of the 8 memory regions should be switched to bank 5, which begins at $05 * $1000 bytes in the ROM image.
Initializing a tune
This is pretty simple. Load the desired song # into the accumulator, minus 1 and set the X register to specify PAL (X=1) or NTSC (X=0). If this is a single standard tune (i.e. PAL *or* NTSC but not both) then the X register contents should not matter. Once the song # and optional PAL/NTSC standard are loaded, simply call the INIT address. Once init is done, it should perform an RTS.
- Clear all RAM at $0000-$07FF and $6000-$7FFF.
- Init the sound registers by writing $00 to $4000-$4013 and $0F to $4015. (The spec originally recommended writing $10 to $4010, but it was since discovered that the APU ignores bits 4 and 5 of this value.)
- If the tune is bankswitched, load the bank values from the header into $5FF8-$5FFF.
- Set the accumulator and X registers for the desired song.
- Call the music init routine.
Playing a tune
Once the tune has been initialized, it can now be played. To do this, simply call the play address several times a second. How many times per second is determined by offsets $006e and $006f in the file. These bytes denote how many microseconds to wait between calls. These playback rates are common:
- 60.002 Hz (recommended by the original NSF specification, close to APU timer IRQ rate): 16666 ($411A)
- 60.099 Hz (actual NTSC NES frame rate): 16640 ($4100)
- 50.007 Hz (PAL NES frame rate): 19997 ($4E1D)
To generate a differing playback rate, use this formula:
1000000 period= --------- speed
Where period is the value you stick into $006e-$006f in the file, and speed is the desired speed in hertz.
Some NSFs use a much faster playback rate than the typical value of one call per frame. These can be played on an emulator or on an NES by treating the playback routine as if it were called by a mapper IRQ handler.
The player should call the play address of the music at periodic intervals determined by the speed words. Which word to use is determined by which mode you are in- PAL or NTSC.
Sound Chip Support
Byte 007bh of the file stores the sound chip flags. If a particular flag is set, those sound registers should be enabled. If the flag is clear, then those registers should be disabled. All I/O registers within 8000-FFFF are write only and must not disrupt music code that happens to be stored there.
APU
- Uses registers 4000-4013, 4015 and 4017. See APU for more information.
- 4015 is set to 0F on reset by most players. It is better if the NSF does not assume this and initializes this register itself, but there are several existing NSF files that require it (Battletoads, Castlevania and Gremlins 2 are examples).
- The interrupts that can be enabled via 4015 and 4017 are not supported by the NSF format.
VRCVI
- Uses registers 9000-9002, A000-A002, and B000-B002, write only. See VRC6 Audio for more information.
- Note: The A0 and A1 lines are flipped on a few games! If you rip the music and it sounds all funny, flip around the xxx1 and xxx2 register pairs. (i.e. 9001 and 9002) 9000 and 9003 can be left untouched. I decided to do this since it would make things easier all around, and this means you only will have to change the music code in a very few places (6). Esper2 and Madara will need this change, while Castlevania 3j will not for instance.
VRCVII
- Uses registers 9010 and 9030, write only. See VRC7 Audio for more information.
FDS Sound
- Uses registers from 4040 through 4092. See FDS Audio for more information.
Notes:
- 6000-DFFF is assumed to be RAM, since 6000-DFFF is RAM on the FDS. E000-FFFF is usually not included in FDS games because it is the BIOS ROM. However, it can be used on FDS rips to help the ripper (for modified play/init addresses).
- Bankswitching operates slightly different on FDS tunes. 5FF6 and 5FF7 control the banks 6000-6FFF and 7000-7FFF respectively. NSF header offsets 76h and 77h correspond to *both* 6000-7FFF *AND* E000-FFFF. Keep this in mind!
MMC5 Sound
- Uses registers 5000-5015, write only as well as 5205 and 5206, and 5C00-5FF5. see MMC5 Audio for more information.
Notes:
- 5205 and 5206 are a hardware 8*8 multiplier. The idea being you write your two bytes to be multiplied into 5205 and 5206 and after doing so, you read the result back out.
- 5C00-5FF5 should be RAM to emulate EXRAM while in MMC5 mode.
Namco 163 Sound
- Uses registers 4800 and F800. See Namco 163 audio for more information.
Sunsoft 5B Sound
- Audio in the Sunsoft 5B mapper, a variant of the FME-7, uses registers C000 and E000. See Sunsoft audio.
Multi-chip tunes
Multiple chips can be used together as long as their registers don't overlap. N163's address port ($F800) overlaps a mirror of Sunsoft 5B's data port ($E000). While writing to the N163, Sunsoft 5B's address port ($C000) should be set to $0E or $0F. VRC6 and VRC7 cannot be used together because the VRC7's ports ($9010 and $9030) overlap a mirror of the VRC6's pulse 1 control port.
Caveats
- The starting song number and maximum song numbers start counting at 1, while the init address of the tune starts counting at 0. To "fix", simply pass the desired song number minus 1 to the init routine.
- The NTSC speed word is used *only* for NTSC tunes, or dual PAL/NTSC tunes. The PAL speed word is used *only* for PAL tunes, or dual PAL/NTSC tunes.
- The length of the text in the name, artist, and copyright fields must be 31 characters or less! There has to be at least a single NULL byte (00h) after the text, between fields.
- If a field is not known (name, artist, copyright) then the field must contain the string "<?>" (without quotes).
- There should be 8K of RAM present at 6000-7FFFh. MMC5 tunes need RAM at 5C00-5FF7 to emulate its EXRAM. 8000-FFFF should be read-only (not writable) after a tune has loaded. The only time this area should be writable is if an FDS tune is being played.
- Do not assume the state of *anything* on entry to the init routine except A and X. Y can be anything, as can the flags.
- Do not assume the state of *anything* on entry to the play routine either. Flags, X, A, and Y could be at any state. I've fixed about 10 tunes because of this problem and the problem, above.
- The stack sits at 1FFh and grows down. Make sure the tune does not attempt to use 1F0h-1FFh for variables. (Armed Dragon Villigust did and I had to relocate its RAM usage to 2xx)
- Variables should sit in the 0000h-07FFh area *only*. If the tune writes outside this range, say 1400h this is bad and should be relocated. (Terminator 3 did this and I relocated it to 04xx).