NSF: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(→‎Properly Initializing a Tune: Simplify description because writing $00 and $10 to that port do the same thing)
(→‎Header Overview: more information about frequency of extended character encodings, Shift-JIS is the more common, used by many Famicompo participants. 1252 Latin I don't have any ready examples for.)
 
(71 intermediate revisions by 9 users not shown)
Line 1: Line 1:
The basic idea is one rips the music/sound code from an NES game and prepends
[[Category:Audio]]
a small header to the data.
[[Category:File formats]]
The NES Sound Format (.nsf) is used for storing and playing music from the NES and related systems. It is similar to the PSID file format for C64 music/sound, where one rips the music/sound code from an NES game and prepends a small header to the data. An NSF player puts the music code into memory at the proper place, based on the header, prepares sound hardware, then runs it to make music. An NSF can be played on NES/Famicom hardware or in an emulator (NSF player or NES emulator).


A program of some form (6502/sound emulator) then takes the data and loads
There are two extensions of the NSF format:
it into the proper place into the 6502's address space, then inits and plays
* [[NSFe]] - Allows a playlist with track titles and times, as well as other metadata.
the tune.
* [[NSF2]] - A backward compatible extension including NSFe's metadata, IRQ and other features.


== Header Overview ==
== Header Overview ==
All 2-byte address and period values are little endian. For example, an NTSC play speed of <code>FF 40</code> means $40FF, or 16639 microseconds.


  offset  # of bytes  Function
  offset  # of bytes  Function
  ----------------------------
  ----------------------------
  0000   5  STRING  "NESM",01Ah  ; denotes an NES sound format file
  $000   5  STRING  'N','E','S','M',$1A (denotes an NES sound format file)
  0005   1  BYTE    Version number (currently 01h)
  $005   1  BYTE    Version number $01 (or $02 for [[NSF2]])
  0006   1  BYTE    Total songs  (1=1 song, 2=2 songs, etc)
  $006   1  BYTE    Total songs  (1=1 song, 2=2 songs, etc)
  0007   1  BYTE    Starting song (1= 1st song, 2=2nd song, etc)
  $007   1  BYTE    Starting song (1=1st song, 2=2nd song, etc)
  0008   2  WORD    (lo/hi) load address of data (8000-FFFF)
  $008   2  WORD    (lo, hi) load address of data ($8000-FFFF)
  000a   2  WORD    (lo/hi) init address of data (8000-FFFF)
  $00A   2  WORD    (lo, hi) init address of data ($8000-FFFF)
  000c   2  WORD    (lo/hi) play address of data (8000-FFFF)
  $00C   2  WORD    (lo, hi) play address of data ($8000-FFFF)
  000e   32  STRING  The name of the song, null terminated
  $00E   32  STRING  The name of the song, null terminated
  002e   32  STRING  The artist, if known, null terminated
  $02E   32  STRING  The artist, if known, null terminated
  004e   32  STRING  The Copyright holder, null terminated
  $04E   32  STRING  The copyright holder, null terminated
  006e   2  WORD    (lo/hi) speed, in 1/1000000th sec ticks, NTSC (see text)
  $06E   2  WORD    (lo, hi) Play speed, in 1/1000000th sec ticks, NTSC (see text)
  0070   8  BYTE    Bankswitch Init Values (see text, and FDS section)
  $070   8  BYTE    Bankswitch init values (see text, and FDS section)
  0078   2  WORD    (lo/hi) speed, in 1/1000000th sec ticks, PAL (see text)
  $078   2  WORD    (lo, hi) Play speed, in 1/1000000th sec ticks, PAL (see text)
  007a   1  BYTE    PAL/NTSC bits, like [[NES 2.0#TV system|NES 2.0 byte 12]]
  $07A   1  BYTE    PAL/NTSC bits
                 bit 0: if clear, this is an NTSC tune
                 bit 0: if clear, this is an NTSC tune
                 bit 0: if set, this is a PAL tune
                 bit 0: if set, this is a PAL tune
                 bit 1: if set, this is a dual PAL/NTSC tune
                 bit 1: if set, this is a dual PAL/NTSC tune
                 bits 2-7: not used. they *must* be 0
                 bits 2-7: reserved, must be 0
  007b   1  BYTE    Extra Sound Chip Support
  $07B   1  BYTE    Extra Sound Chip Support
                 bit 0: if set, this song uses [[VRC6 audio]]
                 bit 0: if set, this song uses [[VRC6 audio]]
                 bit 1: if set, this song uses [[VRC7 audio]]
                 bit 1: if set, this song uses [[VRC7 audio]]
Line 35: Line 38:
                 bit 4: if set, this song uses [[Namco 163 audio]]
                 bit 4: if set, this song uses [[Namco 163 audio]]
                 bit 5: if set, this song uses [[Sunsoft 5B audio]]
                 bit 5: if set, this song uses [[Sunsoft 5B audio]]
                 bits 6,7: future expansion: they *must* be 0
                 bit 6: if set, this song uses [[VT02+_Sound|VT02+ audio]]
  007c   4   ----   4 extra bytes for expansion (must be 00h)
                bit 7: reserved, must be zero
  0080   nnn ----    The music program/data follows
  $07C   1   BYTE   Reserved for [[NSF2]]
$07D    3  BYTES  24-bit length of contained program data.
                If 0, all data until end of file is part of the program.
                If used, can be used to provide [[NSF2#Metadata|NSF2 metadata]]
                in a backward compatible way.
  $080   nnn ----    The music program/data follows


NSF is loosely based on the PSID file format for C64 music/sound.
Strings are usually encoded in plain ASCII. In most game rips Japanese titles have been romanized into plain ASCII. More rarely NSFs have also used extended characters, the most common of which is [https://en.wikipedia.org/wiki/Code_page_932_(Microsoft_Windows) Windows CP-932] (Shift-JIS) for Japanese titles. [https://en.wikipedia.org/wiki/Windows-1252 Windows CP-1252] (Latin) encoding examples may also exist.
 
[[NSF2]] and [[NSFe]] should use UTF-8 instead, or plain ASCII for backward compatibility.


== Loading a tune into RAM ==
== Loading a tune into RAM ==


If offsets 0070h to 0077h have 00h in them, then bankswitching is *not*
If file offsets $070 to $077 have $00 in them, then bank switching is ''not''
used. If one or more bytes are something other than 00h then bankswitching
used. Data should be read from the file beginning at $080 and loaded contiguously
is used. If bankswitching is used then the load address is still used,
into the 6502 address space beginning at the load address until the end of file is reached.
but you now use (ADDRESS AND 0FFFh) to determine where on the first bank
 
to load the data.
Some FDS NSFs use a load address below $8000 to fill in the $6000-7FFF range. It is recommended to use bankswitching to accomplish this instead, because it is not universally supported.
 
=== Bank Switching ===
 
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.


Each bank is 4K in size, and that means there are 8 of them for the
NSF    Address      Register
entire 08000h-0ffffh range in the 6502's address space. You determine where
====  ==========  ========
in memory the data goes by setting bytes 070h through 077h in the file.
$070  $8000-8FFF  $5FF8
These determine the initial bank values that will be used, and hence where
  $071  $9000-9FFF  $5FF9
the data will be loaded into the address space.
$072  $A000-AFFF  $5FFA
$073  $B000-BFFF  $5FFB
$074  $C000-CFFF  $5FFC
$075  $D000-DFFF  $5FFD
$076  $E000-EFFF  $5FFE
$077  $F000-FFFF  $5FFF


Here's an example:
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.
 
==== FDS Bankswitching ====
 
If the FDS expansion is enabled, bank switching operates slightly differently. Two additional registers at $5FF6 and $5FF7 control the banks $6000-6FFF and $7000-7FFF respectively, and the initial load values at $076 and $077 now specify the banks used for $6000-7FFF as well as $E000-FFFF (these regions will both be set up to use the same banks before ''INIT'' is called).
 
Because the FDS has a RAM area at $8000-DFFF for the disk image to be loaded to, that means this area is writable when the FDS expansion is enabled. Some NSF player implementations will treat this like bankswitched RAM, and some players will treat an FDS bank switch operation as a copy into RAM. Hardware players are more likely to use bankswitched RAM.
 
This has a number of caveats:
 
* Writes may be mirrored if the same bank is used in multiple places. Care should be taken to avoid accidental overwrites when the same bank appears more than once in the bankswitch table. In particular, unique banks should be used for memory regions that must be written to.
* Since the FDS itself was incapable of mirrored writes like this and many players will not have them, mirrored writes should not intentionally be used to store the same data in two memory locations. It is a side effect, not a supported feature.
* Writes to the area may or may not persist in the bank written to if it is switched out and then switched back in. This is another side effect that should be accounted for, but not relied upon.
* Writes may or may not persist between songs, depending on whether the NSF player reloads the NSF image when the song is changed. Hardware players are not likely to reload, but software players may.
 
See also the notes on [[#Multi-chip tunes|multi-chip tunes]] below.
 
==== Example ====


METROID.NSF will be used for the following explanation.
METROID.NSF will be used for the following explanation.


  The file is set up like so:  (starting at 070h in the file)
  The file is set up like so:  (starting at $070 in the file)
   
   
  0070: 05 05 05 05 05 05 05 05 - 00 00 00 00 00 00 00 00
  $070: 05 05 05 05 05 05 05 05
  0080: ... music data goes here...
$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 ==
 
The desired song number is loaded into the accumulator register A,
and the X register is set to specify specify PAL (X=1) or NTSC (X=0).
 
Valid song numbers are 0 to one less than the number of songs (specified at $006 in the header).
The first selected song is in the header at $007. The NSF player should display
to the user song numbers from 1 up to and including the number of songs, and these should
correspond to the same number - 1 loaded into register A. Note that when choosing the first song
from the value in $007, subtract 1 from it before loading that value into register A.


Since 0070h-0077h are something other than 00h, then we know that this
# Write $00 to all RAM at $0000-$07FF and $6000-$7FFF.
tune uses bankswitching. The load address for the data is specified as
# Initialize the sound registers by writing $00 to $4000-$4013, and $00 then $0F to $4015.
08000h.  We take this AND 0fffh and get 0000h, so we will load data in
# Initialize the [[APU Frame Counter|frame counter]] to 4-step mode ($40 to $4017).
at byte 0 of bank 0, since data is loaded into the banks sequentially
# If the tune is bank switched, load the bank values from $070-$077 into $5FF8-$5FFF.
starting from bank 0 up until the music data is fully loaded.
# Set the A register for the desired song.
# Set the X register for PAL or NTSC.
# Call the music ''INIT'' routine.


Metroid has 6 4K banks in it, numbered 0 through 5.  The 6502's address
The ''INIT'' routine MUST finish with an RTS instruction before music playback will begin.
space has 8 4K bankswitchable blocks on it, starting at 08000h-08fffh,
At this point, the NSF player will begin executing the ''PLAY'' routine at the specified interval.
09000h-09fffh, 0a000h-0afffh ... 0f000h-0ffffh. Each one of these is 4K in
size, and the current bank is controlled by writes to 05ff8h through 05fffh,
one byte per bank.  So, 05ff8h controls the 08000h-08fffh range, 05ff9h
controls the 09000h-09fffh range, etc. up to 05fffh which controls the
0f000h-0ffffh range.  When the song is loaded into RAM, it is loaded into
the banks and not the 6502's address space.  Once this is done, then the
bank control registers are written to set up the inital bank values.
To do this, the value at 0070h in the file is written to 05ff8h, 0071h
is written to 05ff9h, etc. all the way to 0077h is written to 05fffh.
This is should be done before every call to the init routine.


If the tune was not bankswitched, then it is simply loaded in at the  
If this is a single standard tune (PAL or NTSC but not both) the ''INIT'' routine MAY ignore the X register.
specified load address, until EOF
Otherwise, it SHOULD use this value to determine how to set pitches and tempo for the appropriate platform.


== Initializing a tune ==
The use of the $4017 register is not well supported by existing NSF players. The NSF should not normally clear bit 6 (the IRQ disable bit), though the [[#Pseudo-IRQ Technique|Pseudo-IRQ Technique]] relies on being able to do this.


This is pretty simple.  Load the desired song # into the accumulator,
While the NSF1 specification never guaranteed anything for Y on entry to INIT,
minus 1 and set the X register to specify PAL (X=1) or NTSC (X=0).
for better forward compatibility with [[NSF2#Non-Returning INIT|NSF2's non-returning INIT]] feature,
If this is a single standard tune (i.e. PAL *or* NTSC but not both)
it is recommended that the player set Y to 0, or at least some value that is not $80 or $81, before calling INIT.
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.


== Playing a tune ==
== Playing a tune ==


Once the tune has been initialized, it can now be played.
Once the tune has been initialized, it can now be played.
To do this, simply call the play address several times a second.
To do this, simply call the routine at the ''PLAY'' address at the rate
How many times per second is determined by offsets $006e and $006f in the file.
determined by the file header at $06E-06F (NTSC) or $078-079 (PAL).
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 [[Clock rate|frame rate]]): 16640 ($4100)
* 50.007 Hz (PAL NES frame rate): 19997 ($4E1D)


To generate a differing playback rate, use this formula:
The playback rate is determined by this formula:


          1000000
        1000000                  1000000
  period= ---------
  rate = ---------      period = ---------
          speed
        period                    speed


Where period is the value you stick into $006e-$006f in the file, and
Where period is the value you place at $06E-$06F in the file, and
speed is the desired speed in hertz.
rate is how often the ''PLAY'' routine should be called in Hz.


Some NSFs use a much faster playback rate than the typical value of one call per frame.
The following playback rates are common:
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.
* 60.002 Hz (recommended by the original NSF specification, close to APU timer IRQ rate): 16666 ($411A)
 
* 60.099 Hz (actual NTSC NES [[Cycle_reference_chart#Clock_rates|frame rate]]): 16639 ($40FF)
== Properly Loading a Tune ==
* 50.007 Hz (suggested PAL NES frame rate): 19997 ($4E1D)
 
;If the tune is bankswitched
:Load the data into the CPU address space starting at load_address;
;If the tune is not bankswitched
:Load the data starting at (start_address AND 0FFFh) and stop.


== Properly Initializing a Tune ==
Nonstandard rates may be difficult for hardware players. If the rate is much faster the ''PLAY'' routine may not be short enough to execute in the specified amount of time.


# Clear all RAM at $0000-$07FF and $6000-$7FFF.
The ''PLAY'' routine will be called at the specified interval. If the X register passed to ''INIT'' was 1 (PAL), it will be called at the rate specified by $078-079, and if 0 (NTSC), it will  use the rate at $06E-06F.
# 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.


== Properly Playing a Tune ==
A ''PLAY'' routine should normally finish with an RTS instruction, but is not required to do so.
A non-returning ''PLAY'' will cause problems for NSF players that use the same CPU to control the user interface and to run the NSF, such as NSF players that run on an NES.
It is strongly recommended to return every few frames if at all possible, such as when no PCM is playing.
If ''PLAY'' takes longer to finish than the specified interval, that interval may be skipped and ''PLAY'' may not be called again until the next one.


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.
Some popular modern NSF engines use a non-returning ''PLAY'' to implement an output stream of PCM sound (e.g. SuperNSF, MUSE, Deflemask), and this can also be combined with a [[#Pseudo-IRQ Technique|Pseudo-IRQ technique]].


== Sound Chip Support ==
== 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.
Byte $07B 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. Some audio register addresses have mirrors in their original hardware mappers, but NSF code should use only the lowest address for each register, listed here.


=== APU ===
=== APU ===
* Uses registers 4000-4013, 4015 and 4017. See [[APU]] for more information.
* Uses registers $4000-4013, and $4015. 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).
* $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.
* The APU interrupts that can be generated via $4015 and $4017 are not reliably available across NSF players, and have usually been considered out of bounds for NSF rips. [[NSF2]] can explicitly allow them, however.
* $4017 has other features that are not consistently supported across NSF players.


=== VRCVI ===
=== VRCVI ===
* Uses registers 9000-9002, A000-A002, and B000-B002, write only. See [[VRC6_audio|VRC6 Audio]] for more information.
* Uses registers $9000-9003, $A000-A002, and $B000-B002, write only. See [[VRC6_audio|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.
* 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) Esper2 and Madara will need this change, while Castlevania 3j will not.


=== VRCVII ===
=== VRCVII ===
* Uses registers 9010 and 9030, write only. See [[VRC7_audio|VRC7 Audio]] for more information.
* Uses registers $9010 and $9030, write only. See [[VRC7_audio|VRC7 Audio]] for more information.


=== FDS Sound ===
=== FDS Sound ===
* Uses registers from 4040 through 4092. See [[FDS_audio|FDS Audio]] for more information.
* Uses registers from $4040 through $4092. See [[FDS_audio|FDS Audio]] for more information.


Notes:
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).
* $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!
* Bank switching is different if FDS is enabled. $5FF6 and $5FF7 control banks at $6000-6FFF and $7000-7FFF, and the NSF header $076-$077 initialized both $6000-7FFF and $E000-FFFF. See above.


=== MMC5 Sound ===
=== MMC5 Sound ===
* Uses registers 5000-5015, write only as well as 5205 and 5206, and 5C00-5FF5. see [[MMC5_audio|MMC5 Audio]] for more information.
* Uses registers $5000-5015, write only as well as $5205 and $5206, and $5C00-5FF5. see [[MMC5_audio|MMC5 Audio]] for more information.


Notes:
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.
* $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.
* $5C00-5FF5 should be RAM to emulate EXRAM while in MMC5 mode.


=== Namco 106 Sound ===
=== Namco 163 Sound ===
* Uses registers 4800 and F800. See [[Namco_106_audio|Namco 106 Audio]] for more information.
* Uses registers $4800 and $F800. See [[Namco 163 audio]] for more information.


=== Sunsoft 5B Sound ===
=== Sunsoft 5B Sound ===
* Audio in the Sunsoft 5B mapper, a variant of the [[FME-7]], uses registers C000 and E000. See [[Sunsoft audio]].
* Audio in the Sunsoft 5B mapper, a variant of the [[FME-7]], uses registers $C000 and $E000. See [[Sunsoft audio]].
* Many players do not implement the noise or envelope capabilities of the 5B, as they were not used in the only 5B game, Gimmick.
 
=== Multi-chip tunes ===
 
Multiple expansion chips can be used at the same time, but because this was not something that was ever supported by an original Famicom games, actual practice with multi-expansion NSF varies.
 
Some mappers mirror their audio registers at addresses that would conflict. Many NSF players only support the lowest address, which avoids these conflicts, but the following conflicts may need resolution in an attempted hardware multi-chip implementation:
 
* N163's address port $F800 overlaps a mirror of Sunsoft 5B's data port $E000. This can be avoided by setting Sunsoft 5B's address port $C000 to $0E or $0F (unused internal registers) before writing to the N163.
* VRC6 and VRC7 have a conflict at ports $9010 and $9030, where the VRC6's pulse 1 control port is mirrored.
* VRC7 and N163 each have a mute or reset register at $E000, which conflicts with Sunsoft 5B's data port. Since writing $E000 with bit 6 set will silence either of these, an emulator may wish to ignore writes to $E000 for VRC7/N163 if 5B is also present.
* FDS will make the normally read-only area from $8000-$DFFF writable. This may cause corruption of these areas when writing to VRC6, VRC7, or 5B audio registers. The safest way to avoid this is to make sure your code and data do not fall within these addresses, so that you may safely write to them. NSF player implementations may wish to disable memory writes at these addresses to avoid the conflict.


== Caveats ==
== 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 starting song number and maximum song numbers start counting at 1, while the ''INIT'' address of the tune starts counting at 0.  Remember to 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 NTSC speed word is used ''only'' for NTSC tunes and dual PAL/NTSC tunes. The PAL speed word is used ''only'' for PAL tunes and dual PAL/NTSC tunes.
# The length of the text in the name, artist, and copyright fields must be 31 characters or lessThere has to be at least a single NULL byte (00h) after the text, between fields.
* If bit 1 of the PAL/NTSC is set, indicating a dual PAL/NTSC NSF, bit 0 may be interpreted as a preference for PAL or NTSC. Most players do not support this, however, and some older players may have problems if bit 0 is set.
# If a field is not known (name, artist, copyright) then the field must contain the string "<?>" (without quotes).   
* 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 ($00) after the text, between fields.
# 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.
* If a field is not known (name, artist, copyright) then the field must contain the string "<?>" (without quotes).   
# 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.
* There should be 8K of RAM present at $6000-7FFF. 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 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.
* 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.
# 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)
* Do not assume the state of ''anything'' on entry to the ''PLAY'' routine. Flags, X, A, and Y could be at any state.
# 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).
* The stack sits at $01FF and grows down. The precise position of the stack on ''INIT'' or ''PLAY'' is not guaranteed, as the NSF player may need to use the top area of the stack for its own internal purpose. Make sure the tune does not attempt to modify $01F0-01FF directly. (Armed Dragon Villigust did, and was relocated to 2xx for its NSF.)
* The NSF should not initialize the stack pointer in ''INIT'' or ''PLAY''. These subroutines are called from the player; some software emulators may not have a problem with this, but it will almost certainly cause an error on a hardware player. It is the player's job to initialize the stack pointer, and some hardware players (e.g. [[PowerPak]]) will place their own variables on the stack.
* RAM should be addressed from $0000-07FF, and should not expect mirror addresses to work. If the tune writes outside this range, e.g. $1400 it should be relocated. (Terminator 3 did this and was relocated to 04xx for NSF.)
* The vector table at $FFFA-FFFF should not be filled with code or data by the NSF. These can be overridden by hardware NSF players.
* Instructions which modify the stack, PLP, PHP, and TXS must be used with great care, as a player may need to rely on being able to store data at the end of the stack. An NSF should use the stack pointer given; the stack past this pointer should remain intact, as it may be needed by the player.
* Instructions CLI, SEI, and BRK are problematic, and should usually be avoided. The NSF itself should generally not attempt to interfere with IRQs, as many NSF players do not have an IRQ implementation. One notable exception is using SEI in a non-returning ''PLAY'' routine for a [[#Pseudo-IRQ Technique|pseudo-IRQ technique]]. BRK should generally not be used, as it reads the IRQ routine address from the vector table which is reserved for the player's use.
* PowerPak's NSF play incorrectly does not restore the startup banks when switching tracks, so unless the PLAY routine always leaves with the INIT routine in its starting bank, switching tracks will fail on it.
 
== Summary of Addresses ==
 
These lists all the addresses which should be readable by the code in the NSF; no other addresses should ever be accessed for reading:
* $0000-$01EF
* $01F0-$01FF (may be used internally by NSF player)
* $0200-$07FF
* $4015
* $4040-$407F (if FDS is enabled)
* $4090 (if FDS is enabled)
* $4092 (if FDS is enabled)
* $4800 (if Namco 163 is enabled)
* $5205-$5206 (if MMC5 is enabled)
* $5C00-$5FF5 (if MMC5 is enabled)
* $6000-$FFF9
 
These lists all the addresses which should be writable by the code in the NSF; no other addresses should ever be accessed for writing:
* $0000-$01EF
* $01F0-$01FF (may be used internally by NSF player; do not use for non-stack variables)
* $0200-$07FF
* $4000-$4013 (always clear bit7 of $4010)
* $4015
* $4040-$4080 (if FDS is enabled)
* $4082-$408A (if FDS is enabled)
* $4800 (if Namco 163 is enabled)
* $5205-$5206 (if MMC5 is enabled)
* $5C00-$5FF5 (if MMC5 is enabled)
* $5FF6-$5FF7 (if bankswitching and FDS is enabled)
* $5FF8-$5FFF (if bankswitching is enabled)
* $6000-$7FFF
* $8000-$DFFF (if FDS is enabled)
* $9000-$9003 (if VRC6 is enabled)
* $9010 (if VRC7 is enabled)
* $9030 (if VRC7 is enabled)
* $A000-$A002 (if VRC6 is enabled)
* $B000-$B002 (if VRC6 is enabled)
* $F800 (if Namco 163 is enabled)
 
Reading/writing anything other than specified here results in undefined behaviour.
 
== Pseudo-IRQ Technique ==
 
Some modern NSFs use a trick<ref>[http://forums.nesdev.org/viewtopic.php?f=6&t=9296 NSF PCM technique (via Deflemask)] forum post</ref> first made popular by [http://www.delek.com.ar/deflemask Deflemask], primarily intended to support PCM sample playback. This technique is not universally supported, because it may rely on a lack of conflict with the player's implementation. Some hardware implementations do support it correctly (e.g. [[PowerPak]]), and it also works with several software NSF players.
 
The technique uses a non-returning ''PLAY'' in the following way:
 
# Use SEI to mask interrupts.
# Enable the APU interrupt by writing to $4017.
# Enter a sample playback loop, polling $4015 to see if an APU IRQ is pending.
# When the poll registers the APU IRQ flag (occurring at 60 hz on NTSC), temporarily exit the sample playback loop to do other tasks.
# Return to step 3, never returning from ''PLAY''.


== See also ==
== See also ==
*[[List of NES music composers]]
*[[List of NES music composers]]
*[[Emulation Libraries#NSF Players|Emulation Libraries: NSF Players]]
*[[iNES Mapper 031]]: Cart mapper with NSF-inspired bankswitching
*[[NSFDRV]]
== References ==
* [http://kevtris.org/nes/nsfspec.txt Kevtris' Official NSF spec] - the original NSF specification
* [http://kevtris.org/Projects/hardnes/index.html Kevtris' HardNES] - a hardware NSF player project
<references/>

Latest revision as of 06:18, 22 June 2023

The NES Sound Format (.nsf) is used for storing and playing music from the NES and related systems. It is similar to the PSID file format for C64 music/sound, where one rips the music/sound code from an NES game and prepends a small header to the data. An NSF player puts the music code into memory at the proper place, based on the header, prepares sound hardware, then runs it to make music. An NSF can be played on NES/Famicom hardware or in an emulator (NSF player or NES emulator).

There are two extensions of the NSF format:

  • NSFe - Allows a playlist with track titles and times, as well as other metadata.
  • NSF2 - A backward compatible extension including NSFe's metadata, IRQ and other features.

Header Overview

All 2-byte address and period values are little endian. For example, an NTSC play speed of FF 40 means $40FF, or 16639 microseconds.

offset  # of bytes   Function
----------------------------
$000    5   STRING  'N','E','S','M',$1A (denotes an NES sound format file)
$005    1   BYTE    Version number $01 (or $02 for NSF2)
$006    1   BYTE    Total songs   (1=1 song, 2=2 songs, etc)
$007    1   BYTE    Starting song (1=1st song, 2=2nd song, etc)
$008    2   WORD    (lo, hi) load address of data ($8000-FFFF)
$00A    2   WORD    (lo, hi) init address of data ($8000-FFFF)
$00C    2   WORD    (lo, hi) play address of data ($8000-FFFF)
$00E    32  STRING  The name of the song, null terminated
$02E    32  STRING  The artist, if known, null terminated
$04E    32  STRING  The copyright holder, null terminated
$06E    2   WORD    (lo, hi) Play speed, in 1/1000000th sec ticks, NTSC (see text)
$070    8   BYTE    Bankswitch init values (see text, and FDS section)
$078    2   WORD    (lo, hi) Play speed, in 1/1000000th sec ticks, PAL (see text)
$07A    1   BYTE    PAL/NTSC bits
                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: reserved, must be 0
$07B    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
                bit 6: if set, this song uses VT02+ audio
                bit 7: reserved, must be zero
$07C    1   BYTE    Reserved for NSF2
$07D    3   BYTES   24-bit length of contained program data.
                If 0, all data until end of file is part of the program.
                If used, can be used to provide NSF2 metadata
                in a backward compatible way.
$080    nnn ----    The music program/data follows

Strings are usually encoded in plain ASCII. In most game rips Japanese titles have been romanized into plain ASCII. More rarely NSFs have also used extended characters, the most common of which is Windows CP-932 (Shift-JIS) for Japanese titles. Windows CP-1252 (Latin) encoding examples may also exist.

NSF2 and NSFe should use UTF-8 instead, or plain ASCII for backward compatibility.

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.

Some FDS NSFs use a load address below $8000 to fill in the $6000-7FFF range. It is recommended to use bankswitching to accomplish this instead, because it is not universally supported.

Bank Switching

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.

FDS Bankswitching

If the FDS expansion is enabled, bank switching operates slightly differently. Two additional registers at $5FF6 and $5FF7 control the banks $6000-6FFF and $7000-7FFF respectively, and the initial load values at $076 and $077 now specify the banks used for $6000-7FFF as well as $E000-FFFF (these regions will both be set up to use the same banks before INIT is called).

Because the FDS has a RAM area at $8000-DFFF for the disk image to be loaded to, that means this area is writable when the FDS expansion is enabled. Some NSF player implementations will treat this like bankswitched RAM, and some players will treat an FDS bank switch operation as a copy into RAM. Hardware players are more likely to use bankswitched RAM.

This has a number of caveats:

  • Writes may be mirrored if the same bank is used in multiple places. Care should be taken to avoid accidental overwrites when the same bank appears more than once in the bankswitch table. In particular, unique banks should be used for memory regions that must be written to.
  • Since the FDS itself was incapable of mirrored writes like this and many players will not have them, mirrored writes should not intentionally be used to store the same data in two memory locations. It is a side effect, not a supported feature.
  • Writes to the area may or may not persist in the bank written to if it is switched out and then switched back in. This is another side effect that should be accounted for, but not relied upon.
  • Writes may or may not persist between songs, depending on whether the NSF player reloads the NSF image when the song is changed. Hardware players are not likely to reload, but software players may.

See also the notes on multi-chip tunes below.

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

The desired song number is loaded into the accumulator register A, and the X register is set to specify specify PAL (X=1) or NTSC (X=0).

Valid song numbers are 0 to one less than the number of songs (specified at $006 in the header). The first selected song is in the header at $007. The NSF player should display to the user song numbers from 1 up to and including the number of songs, and these should correspond to the same number - 1 loaded into register A. Note that when choosing the first song from the value in $007, subtract 1 from it before loading that value into register A.

  1. Write $00 to all RAM at $0000-$07FF and $6000-$7FFF.
  2. Initialize the sound registers by writing $00 to $4000-$4013, and $00 then $0F to $4015.
  3. Initialize the frame counter to 4-step mode ($40 to $4017).
  4. If the tune is bank switched, load the bank values from $070-$077 into $5FF8-$5FFF.
  5. Set the A register for the desired song.
  6. Set the X register for PAL or NTSC.
  7. Call the music INIT routine.

The INIT routine MUST finish with an RTS instruction before music playback will begin. At this point, the NSF player will begin executing the PLAY routine at the specified interval.

If this is a single standard tune (PAL or NTSC but not both) the INIT routine MAY ignore the X register. Otherwise, it SHOULD use this value to determine how to set pitches and tempo for the appropriate platform.

The use of the $4017 register is not well supported by existing NSF players. The NSF should not normally clear bit 6 (the IRQ disable bit), though the Pseudo-IRQ Technique relies on being able to do this.

While the NSF1 specification never guaranteed anything for Y on entry to INIT, for better forward compatibility with NSF2's non-returning INIT feature, it is recommended that the player set Y to 0, or at least some value that is not $80 or $81, before calling INIT.

Playing a tune

Once the tune has been initialized, it can now be played. To do this, simply call the routine at the PLAY address at the rate determined by the file header at $06E-06F (NTSC) or $078-079 (PAL).

The playback rate is determined by this formula:

        1000000                  1000000
rate = ---------       period = ---------
        period                    speed

Where period is the value you place at $06E-$06F in the file, and rate is how often the PLAY routine should be called in Hz.

The following 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): 16639 ($40FF)
  • 50.007 Hz (suggested PAL NES frame rate): 19997 ($4E1D)

Nonstandard rates may be difficult for hardware players. If the rate is much faster the PLAY routine may not be short enough to execute in the specified amount of time.

The PLAY routine will be called at the specified interval. If the X register passed to INIT was 1 (PAL), it will be called at the rate specified by $078-079, and if 0 (NTSC), it will use the rate at $06E-06F.

A PLAY routine should normally finish with an RTS instruction, but is not required to do so. A non-returning PLAY will cause problems for NSF players that use the same CPU to control the user interface and to run the NSF, such as NSF players that run on an NES. It is strongly recommended to return every few frames if at all possible, such as when no PCM is playing. If PLAY takes longer to finish than the specified interval, that interval may be skipped and PLAY may not be called again until the next one.

Some popular modern NSF engines use a non-returning PLAY to implement an output stream of PCM sound (e.g. SuperNSF, MUSE, Deflemask), and this can also be combined with a Pseudo-IRQ technique.

Sound Chip Support

Byte $07B 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. Some audio register addresses have mirrors in their original hardware mappers, but NSF code should use only the lowest address for each register, listed here.

APU

  • Uses registers $4000-4013, and $4015. 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 APU interrupts that can be generated via $4015 and $4017 are not reliably available across NSF players, and have usually been considered out of bounds for NSF rips. NSF2 can explicitly allow them, however.
  • $4017 has other features that are not consistently supported across NSF players.

VRCVI

  • Uses registers $9000-9003, $A000-A002, and $B000-B002, write only. See VRC6 Audio for more information.
  • 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) Esper2 and Madara will need this change, while Castlevania 3j will not.

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).
  • Bank switching is different if FDS is enabled. $5FF6 and $5FF7 control banks at $6000-6FFF and $7000-7FFF, and the NSF header $076-$077 initialized both $6000-7FFF and $E000-FFFF. See above.

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

Sunsoft 5B Sound

  • Audio in the Sunsoft 5B mapper, a variant of the FME-7, uses registers $C000 and $E000. See Sunsoft audio.
  • Many players do not implement the noise or envelope capabilities of the 5B, as they were not used in the only 5B game, Gimmick.

Multi-chip tunes

Multiple expansion chips can be used at the same time, but because this was not something that was ever supported by an original Famicom games, actual practice with multi-expansion NSF varies.

Some mappers mirror their audio registers at addresses that would conflict. Many NSF players only support the lowest address, which avoids these conflicts, but the following conflicts may need resolution in an attempted hardware multi-chip implementation:

  • N163's address port $F800 overlaps a mirror of Sunsoft 5B's data port $E000. This can be avoided by setting Sunsoft 5B's address port $C000 to $0E or $0F (unused internal registers) before writing to the N163.
  • VRC6 and VRC7 have a conflict at ports $9010 and $9030, where the VRC6's pulse 1 control port is mirrored.
  • VRC7 and N163 each have a mute or reset register at $E000, which conflicts with Sunsoft 5B's data port. Since writing $E000 with bit 6 set will silence either of these, an emulator may wish to ignore writes to $E000 for VRC7/N163 if 5B is also present.
  • FDS will make the normally read-only area from $8000-$DFFF writable. This may cause corruption of these areas when writing to VRC6, VRC7, or 5B audio registers. The safest way to avoid this is to make sure your code and data do not fall within these addresses, so that you may safely write to them. NSF player implementations may wish to disable memory writes at these addresses to avoid the conflict.

Caveats

  • The starting song number and maximum song numbers start counting at 1, while the INIT address of the tune starts counting at 0. Remember to pass the desired song number minus 1 to the INIT routine.
  • The NTSC speed word is used only for NTSC tunes and dual PAL/NTSC tunes. The PAL speed word is used only for PAL tunes and dual PAL/NTSC tunes.
  • If bit 1 of the PAL/NTSC is set, indicating a dual PAL/NTSC NSF, bit 0 may be interpreted as a preference for PAL or NTSC. Most players do not support this, however, and some older players may have problems if bit 0 is set.
  • 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 ($00) 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-7FFF. 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. Flags, X, A, and Y could be at any state.
  • The stack sits at $01FF and grows down. The precise position of the stack on INIT or PLAY is not guaranteed, as the NSF player may need to use the top area of the stack for its own internal purpose. Make sure the tune does not attempt to modify $01F0-01FF directly. (Armed Dragon Villigust did, and was relocated to 2xx for its NSF.)
  • The NSF should not initialize the stack pointer in INIT or PLAY. These subroutines are called from the player; some software emulators may not have a problem with this, but it will almost certainly cause an error on a hardware player. It is the player's job to initialize the stack pointer, and some hardware players (e.g. PowerPak) will place their own variables on the stack.
  • RAM should be addressed from $0000-07FF, and should not expect mirror addresses to work. If the tune writes outside this range, e.g. $1400 it should be relocated. (Terminator 3 did this and was relocated to 04xx for NSF.)
  • The vector table at $FFFA-FFFF should not be filled with code or data by the NSF. These can be overridden by hardware NSF players.
  • Instructions which modify the stack, PLP, PHP, and TXS must be used with great care, as a player may need to rely on being able to store data at the end of the stack. An NSF should use the stack pointer given; the stack past this pointer should remain intact, as it may be needed by the player.
  • Instructions CLI, SEI, and BRK are problematic, and should usually be avoided. The NSF itself should generally not attempt to interfere with IRQs, as many NSF players do not have an IRQ implementation. One notable exception is using SEI in a non-returning PLAY routine for a pseudo-IRQ technique. BRK should generally not be used, as it reads the IRQ routine address from the vector table which is reserved for the player's use.
  • PowerPak's NSF play incorrectly does not restore the startup banks when switching tracks, so unless the PLAY routine always leaves with the INIT routine in its starting bank, switching tracks will fail on it.

Summary of Addresses

These lists all the addresses which should be readable by the code in the NSF; no other addresses should ever be accessed for reading:

  • $0000-$01EF
  • $01F0-$01FF (may be used internally by NSF player)
  • $0200-$07FF
  • $4015
  • $4040-$407F (if FDS is enabled)
  • $4090 (if FDS is enabled)
  • $4092 (if FDS is enabled)
  • $4800 (if Namco 163 is enabled)
  • $5205-$5206 (if MMC5 is enabled)
  • $5C00-$5FF5 (if MMC5 is enabled)
  • $6000-$FFF9

These lists all the addresses which should be writable by the code in the NSF; no other addresses should ever be accessed for writing:

  • $0000-$01EF
  • $01F0-$01FF (may be used internally by NSF player; do not use for non-stack variables)
  • $0200-$07FF
  • $4000-$4013 (always clear bit7 of $4010)
  • $4015
  • $4040-$4080 (if FDS is enabled)
  • $4082-$408A (if FDS is enabled)
  • $4800 (if Namco 163 is enabled)
  • $5205-$5206 (if MMC5 is enabled)
  • $5C00-$5FF5 (if MMC5 is enabled)
  • $5FF6-$5FF7 (if bankswitching and FDS is enabled)
  • $5FF8-$5FFF (if bankswitching is enabled)
  • $6000-$7FFF
  • $8000-$DFFF (if FDS is enabled)
  • $9000-$9003 (if VRC6 is enabled)
  • $9010 (if VRC7 is enabled)
  • $9030 (if VRC7 is enabled)
  • $A000-$A002 (if VRC6 is enabled)
  • $B000-$B002 (if VRC6 is enabled)
  • $F800 (if Namco 163 is enabled)

Reading/writing anything other than specified here results in undefined behaviour.

Pseudo-IRQ Technique

Some modern NSFs use a trick[1] first made popular by Deflemask, primarily intended to support PCM sample playback. This technique is not universally supported, because it may rely on a lack of conflict with the player's implementation. Some hardware implementations do support it correctly (e.g. PowerPak), and it also works with several software NSF players.

The technique uses a non-returning PLAY in the following way:

  1. Use SEI to mask interrupts.
  2. Enable the APU interrupt by writing to $4017.
  3. Enter a sample playback loop, polling $4015 to see if an APU IRQ is pending.
  4. When the poll registers the APU IRQ flag (occurring at 60 hz on NTSC), temporarily exit the sample playback loop to do other tasks.
  5. Return to step 3, never returning from PLAY.

See also

References