The BFSTM (Binary caFe STreaM) file format is used for storing music streams on Wii U and Nintendo Switch. It is a direct update from its predecessors, BRSTM and BCSTM, and is therefore very similar to them. It is also similar to BFWAV. The file consists of a header along with three sections, INFO, SEEK and DATA. All offsets in the file may be 0xFFFFFFFF if it links to nothing.
File Format
The file starts with a 0x40 byte long header as follows:
Offset |
Type |
Description
|
0x00 |
Char[4] |
File magic. Always FSTM in ASCII.
|
0x04 |
UInt16 |
Byte-order-mark. FE FF for big endian, FF FE for little endian.
|
0x06 |
UInt16 |
Header size. Always 0x40.
|
0x08 |
UInt32 |
Version number.
|
0x0C |
UInt32 |
Size of the file in bytes.
|
0x10 |
UInt16 |
Number of data blocks in the file. Always 3 (INFO, SEEK and DATA).
|
0x12 |
UInt16 |
Padding.
|
0x14 |
UInt16 |
INFO section flag. Always 0x4000.
|
0x16 |
UInt16 |
Padding.
|
0x18 |
Int32 |
INFO offset.
|
0x1C |
UInt32 |
INFO size.
|
0x20 |
UInt16 |
SEEK section flag. Always 0x4001.
|
0x22 |
UInt16 |
Padding.
|
0x24 |
Int32 |
SEEK offset.
|
0x28 |
UInt32 |
SEEK size.
|
0x2C |
UInt16 |
DATA section flag. Always 0x4002.
|
0x2E |
UInt16 |
Padding.
|
0x30 |
Int32 |
DATA offset.
|
0x34 |
UInt32 |
DATA size.
|
0x38 |
Byte[8] |
Padding.
|
0x40 |
End of file header
|
Reference Table
A reference table is used to reference multiple structures. It has the following structure:
Offset |
Type |
Description
|
0x00 |
UInt32 |
Number of references.
|
The following structure follows. The amount is specified above.
Offset |
Type |
Description
|
0x00 |
UInt16 |
Section flag, to identify what structure it links to.
|
0x02 |
UInt16 |
Padding.
|
0x04 |
Int32 |
Offset to a structure, relative to the start of the header structure.
|
INFO
The INFO section contains general information about the stream.
Offset |
Type |
Description
|
0x00 |
Char[4] |
Section magic. Always INFO in ASCII.
|
0x04 |
UInt32 |
Size of this section in bytes.
|
0x08 |
UInt16 |
Stream info flag. Always 0x4100.
|
0x0A |
UInt16 |
Padding.
|
0x0C |
Int32 |
Stream info offset, relative to 0x08 in this structure.
|
0x10 |
UInt16 |
Track info flag. Often not used and therefore set to 0.
|
0x12 |
UInt16 |
Padding.
|
0x14 |
Int32 |
Track info offset, relative to 0x08 in this structure.
|
0x18 |
UInt16 |
Channel info flag. Always 0x0101.
|
0x1A |
UInt16 |
Padding.
|
0x1C |
Int32 |
Channel info offset, relative to 0x08 in this structure.
|
Stream Info
Offset |
Type |
Description
|
0x00 |
Byte |
Sound encoding. 0 = PCM8, 1 = PCM16, 2 = DSP ADPCM, 3 = IMA ADPCM.
|
0x01 |
Byte |
Loop. 1 if it loops.
|
0x02 |
Byte |
Number of channels.
|
0x03 |
Byte |
Number of regions.
|
0x04 |
UInt32 |
Sample rate.
|
0x08 |
UInt32 |
Loop start.
|
0x0C |
UInt32 |
Loop end.
|
0x10 |
UInt32 |
The total number of blocks, including the padded one. If this field is N, S is the size of one block and P is the size of a last padded block, then the size of one channel is (N - 1) * S + P.
|
0x14 |
UInt32 |
Size of one block in bytes.
|
0x18 |
UInt32 |
Size of one block in samples.
|
0x1C |
UInt32 |
Size of the last block without padding in bytes.
|
0x20 |
UInt32 |
Size of the last block without padding in samples.
|
0x24 |
UInt32 |
Size of the last block with padding in bytes. The last block is always aligned. PCM8 audio is aligned by 0x20 and PCM16 audio is aligned by 0x04.
|
0x28 |
UInt32 |
Size of one channel's seek info for one block, which should be 4, given the History Info should be 4 bytes long in almost all cases.
|
0x2C |
UInt32 |
SEEK sample interval. The number of samples between each history sample into the SEEK block.
|
0x30 |
UInt16 |
Sample data flag. Always 0x1F00.
|
0x32 |
UInt16 |
Padding.
|
0x34 |
Int32 |
Sample data offset, relative to 0x08 into the DATA block. Offset to the sample data of the first channel.
|
0x38 |
UInt16 |
Size of each region info in bytes. Always 0x100, even when unused.
|
0x3A |
UInt16 |
Padding.
|
0x3C |
UInt16 |
Region info flag. Always 0, even when offset is used.
|
0x3E |
UInt16 |
Padding.
|
0x40 |
Int32 |
Region info offset, relative to 0x08 into the REGN block.
|
If version ≥ 0.4.0.0
|
0x44 |
UInt32 |
Original loop start.
|
0x48 |
UInt32 |
Original loop end.
|
If version ≥ 0.5.0.0
|
0x4C |
UInt32 |
CRC-32 checksum of the whole file with this field set to 0. It is used to match BFSTM and BFSTP when using prefetch.
|
Track Info
The INFO section links to a reference table which points to this structure. Since v0.2.0.0, this structure is no longer exported and is therefore useless.
Offset |
Type |
Description
|
0x00 |
Byte |
Volume.
|
0x01 |
Byte |
Pan.
|
0x02 |
Byte |
Span.
|
0x03 |
Byte |
Flags.
ID |
Type
|
0x00 |
Monaural
|
0x01 |
Stereo
|
0x02 |
Surround
|
0x03 |
Dpl2
|
|
0x04 |
UInt16 |
Global channel index table flag.
|
0x06 |
UInt16 |
Padding.
|
0x08 |
Int32 |
Offset to the global channel index table.
|
Global Channel Index Table
The Global Channel Index Table is used to bundle the local channel index in the track with the global channel index for the overall stream. It has the following structure:
Offset |
Type |
Description
|
0x00 |
UInt32 |
C = Count.
|
0x04 |
Byte[C] |
Items.
|
Channel Info
The INFO section links to a reference table which points to the following structure. The section flag is set to 0x4102.
Offset |
Type |
Description
|
0x00 |
UInt16 |
Section flag. Always 0x0300.
|
0x02 |
UInt16 |
Padding.
|
0x04 |
Int32 |
Offset to DSP ADPCM channel info, relative to the start of this structure.
|
DSP ADPCM Channel Info
Offset |
Type |
Description
|
0x00 |
UInt16[8][2] |
16-bit Coefficients.
|
0x20 |
UInt16 |
Pred scale.
|
0x22 |
UInt16 |
Yn 1.
|
0x24 |
UInt16 |
Yn 2.
|
0x26 |
UInt16 |
Loop Pred Scale.
|
0x28 |
UInt16 |
Loop Yn 1.
|
0x2A |
UInt16 |
Loop Yn 2.
|
0x2C |
UInt16 |
Padding.
|
SEEK
The SEEK section is only used for DSP ADPCM audio. It contains information about midstream playback. It contains info about history samples mid-playback in case the game needs to skip to a certain section of the song. The history samples for the first block in each channel is always 0.
Offset |
Type |
Description
|
0x00 |
Char[4] |
Section magic. Always SEEK in ASCII.
|
0x04 |
UInt32 |
Size of this section in bytes (S).
|
0x08 |
HistoryInfo[Number of blocks][Number of channels] |
History information.
|
History Info:
Offset |
Type |
Description
|
0x00 |
Int16 |
History sample 1. The index to the sample in PCM16 data is the Seek Interval * Block Number - 1.
|
0x02 |
Int16 |
History sample 2. The index to the sample in PCM16 data is the Seek Interval * Block Number - 2.
|
REGN
The REGN section devides the data into different regions. It starts with the following structure:
Offset |
Type |
Description
|
0x00 |
Char[4] |
Section magic. Always REGN in ASCII.
|
0x04 |
UInt32 |
Size of this section in bytes.
|
Region
The number of regions is specified in the stream info into the INFO block. Each entry consists of the following:
Offset |
Type |
Description
|
0x00 |
UInt32 |
Start of the region in samples.
|
0x04 |
UInt32 |
End of the region in samples.
|
After comes 16 entries, representing up to 16 channel loop context. Unused entries are filled with 0. Each entry has the following structure:
Offset |
Type |
Description
|
0x00 |
UInt16 |
Loop Pred Scale.
|
0x02 |
UInt16 |
Loop Yn 1.
|
0x04 |
UInt16 |
Loop Yn 2.
|
0x98 bytes of padding are placed to align each region to be 0x100 bytes long.
DATA
The DATA section holds all the data for the stream. It has the following structure:
Offset |
Type |
Description
|
0x00 |
Char[4] |
Section magic. Always DATA in ASCII.
|
0x04 |
UInt32 |
Size of this section in bytes (S).
|
0x08 |
Byte[S - 8] |
Sound data.
|
Version List
Version |
Found in
|
0.3.0.0
|
|
0.4.0.0
|
|
0.5.0.0
|
|
0.6.1.0
|
|
0.6.3.0
|
|
0.6.4.0
|
|
2.0.0.0
|
|
2.0.1.0
|
|
Tools
The following tools can handle BFSTM files: