S3M Format

From ModdingWiki
Jump to: navigation, search
Edge of map!
S3M Format
Format typeMusic
Notation typeTracked
InstrumentsPCM, OPL
Max channel count32
Max track count255
Max pattern count65,536
Max order count65,536
Tags?Title, instrument names

S3M Format is used to save modules composed in ScreamTracker 3. A number of games support music in this format, however it is primarily used for composing independent songs unrelated to games.

The format is notable both for its popularity, as well as for being one of the few that support both FM/OPL and sampled instruments.

File format

The file begins with a header.

Data type Name Description
char[28] title Song title, must be null-terminated
UINT8 sig1 Signature byte, always 0x1A
UINT8 type Song type, always 0x10 for S3M
UINT16LE reserved Always 0x0000
UINT16LE orderCount Number of entries in the order table, should be even
UINT16LE instrumentCount Number of instruments in the song
UINT16LE patternPtrCount Number of pattern parapointers in the song
UINT16LE flags See below
UINT16LE trackerVersion upper four bits is tracker ID, lower 12 bits is tracker version
UINT16LE sampleType 1=signed samples [deprecated], 2=unsigned samples
char[4] sig2 Signature: "SCRM"
UINT8 globalVolume
UINT8 initialSpeed Frames per row, can be changed later with A command
UINT8 initialTempo Frames per second, can be changed later with T command
UINT8 masterVolume bit 7: 1=stereo, 0=mono, bits 6-0: volume
UINT8 ultraClickRemoval Number of channels to use for click removal on real GUS hardware
UINT8 defaultPan 252=read pan values in header, anything else ignores pan values in header
BYTE[8] reserved Unused, some trackers store data here
UINT16LE ptrSpecial Parapointer to additional data, if flags has bit 7 set
UINT8[32] channelSettings See below
UINT8[orderCount] orderList Which order patterns are played in
UINT16LE[instrumentCount] ptrInstruments List of parapointers to each instrument's data
UINT16LE[patternPtrCount] ptrPatterns List of parapointers to each pattern's data

Flags are one or more values below:

Bit Value Description
0 1 ST2 vibrato [deprecated]
1 2 ST2 tempo [deprecated]
2 4 Amiga slides [deprecated]
3 8 0vol optimisations - automatically turn off looping notes when the volume is zero for more than two rows
4 16 Amiga limits - ignore notes beyond Amiga hardware limits (as Amiga does.) Sliding up stops at B#5. Also affects other Amiga compatibility issues.
5 32 Enable SoundBlaster filter/sfx [deprecated]
6 64 ST3.00 volume slides - perform volume slides on first row as well. Set implicitly if trackerVersion is 0x1300.
7 128 ptrSpecial is valid

Known trackerVersion values are:

Value Description
0x1300 ScreamTracker 3.00
0x1301 ScreamTracker 3.01
0x1303 ScreamTracker 3.03
0x1320 ScreamTracker 3.20
0x2nyy Imago Orpheus x.yy
0x3nyy Impulse Tracker x.yy
0x4nnn Schism Tracker (old BeRoTracker version from between 2004 and 2012 identify as 0x4100)
0x5nyy OpenMPT x.yy
0x6nyy BeRoTracker x.yy
0x7nyy CreamTracker x.yy
0xCA00 Camoto/libgamemusic

channelSettings is 32 values indicating the audio channel assignments for each of the 32 S3M channels. Unused channels should be set to 255.

Value Description
0 to 7 Left PCM channels 1 to 8
8 to 15 Right PCM channels 1 to 8
16 to 24 Adlib melody channel 1-9
25 Adlib percussion channel: bass drum
26 Adlib percussion channel: snare drum
27 Adlib percussion channel: tom tom
28 Adlib percussion channel: top cymbal
29 Adlib percussion channel: hi-hat
30 to 127 Unused/invalid
128 to 254 Unused/invalid (but channel disabled)
255 Channel unused

orderList contains the index of each pattern to be played. The first entry in this array is the index of the first pattern to play, the second entry is the second pattern, etc. If an entry is 0xFE then it is a "marker pattern" and is skipped during playback, and an entry of 0xFF signifies the end of the song.

ptrInstruments and ptrPatterns are arrays of parapointers to the start of the instrument and pattern data. Each parapointer is an offset from the start of the file, in units of 16 bytes (a "paragraph"). To convert this into a normal byte-level file offset, multiply it by 16 (or shift-left by 4.)

By convention these blocks follow the header above, but this is not a requirement and they can occur at any point in the file.


The initialTempo and initialSpeed values are the ones to use until optionally changed during playback, with the A and T effects respectively.

The initialTempo value controls how many audio frames are generated per second. If this value is 50, then there should be 50 audio frames per second. Obviously the more audio frames per second, the shorter each frame is going to be. To calculate the length of each frame, a formula like this can be used:

   frame length in seconds = 1 / initialTempo
    0.02 seconds per frame = 1 / 50

The initialSpeed value controls how many audio frames comprise a single row of the song. If the value is 3, then there are three audio frames per row. For certain effects, they are updated once per frame (i.e. the effect changes between rows.)

To calculate playback speed, both these values need to be taken into account. The tempo value controls the length of each audio frame, while the speed value controls how quickly the rows are turned into those audio frames. For example, to calculate the number of rows per second:

   rowsPerSecond = initialTempo / initialSpeed


At the offset given by an instrument's parapointer, the data has a header as follows:

Data type Name Description
UINT8 type 0=empty instrument (message only), 1=PCM instrument
char[12] filename Original instrument filename in DOS 8.3 format, no terminating null
Value Description
0 empty instrument (message only)
1 PCM instrument
2 Adlib melody instrument
3 Adlib percussive: bass drum
4 Adlib percussive: snare
5 Adlib percussive: tom tom
6 Adlib percussive: top cymbal
7 Adlib percussive: hi-hat

The data following the header depends on whether the instrument is PCM or Adlib. ! What if the instrument is empty, is there any trailing data?


Data type Name Description
UINT8 ptrDataH Upper eight bits of parapointer to sample data, relative to start of S3M file
UINT16LE ptrDataL Lower 16 bits of parapointer to sample data, relative to start of S3M file
UINT32LE length Sample data length, in bytes. S3M is limited to 64000 and ignores upper 16 bits.
UINT32LE loopStart Offset of loop start in bytes, relative to start of sample data.
UINT32LE loopEnd Offset of loop end in bytes, relative to start of sample data.
UINT8 volume Default volume of sample, 0-63 inclusive.
UINT8 reserved Always 0x00
UINT8 pack 0=unpacked, 1=DP30ADPCM [deprecated]
UINT8 flags Sum: 1=loop on, 2=stereo (data is length bytes for left channel then length bytes for right channel), 4=16-bit little-endian sample
UINT32LE c2spd Sample rate for middle-C note (C-4)
BYTE[12] internal Always zero, used in-memory during playback
char[28] title Sample title, for display to user. Must be null-terminated.
char[4] sig Signature: "SCRS"

ScreamTracker stores the above instrument structures at the start of the file, but stores the sample data at the end of the file (after the pattern data.) This is not the only way to store it though.


Data type Name Description
UINT8[3] reserved Always 0x00 0x00 0x00
UINT8[12] oplValues See below
UINT8 volume Default volume of instrument, 0-63 inclusive.
UINT8 dsk ! Unknown
UINT16LE reserved Always 0x0000
UINT32LE c2spd Sample rate for middle-C note (C-4), see below.
BYTE[12] unused Always zero
char[28] title Sample title, for display to user. Must be null-terminated.
char[4] sig Signature: "SCRI"

The oplValues are stored as follows:

Byte index Operator OPL base register Bits
7 6 5 4 3 2 1 0
0 Modulator 0x20 Tremolo? Vibrato? Sustain? KSR? Freq. mult.
1 Carrier 0x23
2 Modulator 0x40 Scale level (bit 0) Scale level (bit 1) Output level (0=loudest, 63=silent)
3 Carrier 0x43
4 Modulator 0x60 Attack rate Decay rate
5 Carrier 0x63
6 Modulator 0x80 Sustain rate Release rate
7 Carrier 0x83
8 Modulator 0xE0 Wave select
9 Carrier 0xE3
10 Modulator 0xC0 Feedback Connection
11 - - Unused, set to 0x00

c2spd sets the instrument tuning. It translates the note freq just like with PCM instruments. The default value of 8363 (as with PCM instruments) means that middle-C plays at about 261.63 Hz (A440 pitch standard), and e.g. doubling it also doubles the middle-C frequency, as with samples.


  • The value packing is almost identical to that used in the SBI Format, just the bytes are in a different order.
  • The ST3 docs say bytes 2-3 bits 5-0 are "63-volume" but this is to make the values match PCM samples. The value in the file matches the value sent to the OPL chip.
  • The Scale Level bits in bytes 2-3 are swapped. The ST3 technical docs have a typo that suggest Scale Level (bit 1) actually overflows into "bit 8" of the OPL register, but testing this in ST3 shows this is not the case and the bit order is merely swapped.
  • The ST3 docs say bytes 6-7 have the sustain rate stored as "15-sustain", which is from a editor UI perspective - the value can be sent as-is to the OPL chip.


At the offset given by a pattern's parapointer, packed data is present and will need to be unpacked. The following structure appears at the start of each pattern's data:

Data type Name Description
UINT16LE packed_len Length of packed data for all 64 rows, in bytes
BYTE[packed_len - 2] packed_data Packed row data, described below

packed_len includes its own length, so as it is two bytes long, the length of the packed data will be two bytes less than this value. The first byte in packed_data is a bitfield called what, and it is broken up as follows:

7 6 5 4 3 2 1 0
command and info present volume present note and instrument present Channel number

If the whole byte is zero then it signals the end of the row. This byte and the ones following are further described in the following table.

Data type Name Description
UINT8 what 0=end of row, lower five bits (what & 0x1F) are channel number
UINT8 note Note number (only present if what & 0x20)
UINT8 instrument Instrument number (only present if what & 0x20)
UINT8 volume Volume level (only present if what & 0x40)
UINT8 command Effect type (only present if what & 0x80)
UINT8 info Effect value (only present if what & 0x80)

After these bytes the process repeats with another what value. When what is 0x00 the end of the row has been reached. After the 64th row has been reached, the pattern ends and packed_len bytes will have been read.

Be aware that channel is a value between 0 and 31 inclusive, which corresponds to an entry in the channelSettings field in the header.

The volume field is 0 for silent, 64 for full volume (note this is 65 unique values), or 255 for 'ignore' (shown as ".." in the tracker.) If the value is 255 or missing entirely, the instrument's default volume is used (the volume value from the instrument settings.)

The upper four bits of note store the octave, and the lower four bits store the semitone (with 0=C, 1=C#, up to 11=B)


0x01/A: Set speed

Set speed (one of the two tempo variables.) Data byte is new speed. A value of 0 causes the event to be ignored.

0x02/B: Order jump

After the current row has finished playing, the next row is the first row in order given by the data byte. 0 means the start of the song ! Confirm this.

0x03/C: Jump to row

After the current row has finished playing, the next row is played from the next pattern in the order sequence. The row in this next pattern is given by the data byte, but the data byte is decimal-as-hex. So a value of 0x12 should be treated as decimal 12. These formulae will calculate the correct row (to/from the S3M value):

row = (data >> 4) * 10 + (data & 0x0f)    // Read S3M into variable
data = ((row / 10) << 4) | (row % 10)     // Write variable to S3M

The first row in the pattern is 0. If the decoded data value is larger than 63, the effect is ignored.


The following tools are able to work with files in this format.

Name PlatformPlay? Create new? Modify? Convert/export to other? Import from other? Access hidden data? Edit metadata? Notes
SchismTracker Windows/LinuxYesYesYes.it + more.mod .it + moreNoYes Can play OPL and PCM simultaneously
ScreamTracker 3 DOSYesYesYes.mod.modNoYes Official tool

External links

Much of this information was combined from the following sites: