
FNK FORMAT
----------


From: Jari Karppinen <jakarppi@paju.oulu.fi>
To: jsno@amigar.apana.org.au
Subject: Funktracker file format

]Hi!
]
]The format description included in FunkTracker archive wasn't very
]understandable. I guess that because I don't code ASM, I couldn't really
]understand it (so it's my fault). But I just thought to ask, if you could
]give me a better description of the FNK format? I think this kind of desc
]
]is quite readable:
]
]OFFSET | LENGHT | DESCRIPTION
]etc.
]
]I hope you help me out with this...
]
]Jari Karppinen       Int: jakarppi@paju.oulu.fi
]Vaskitie 10 B 12       Tel: +358-81-335602
]90250 Oulu
]Finland

ok, i'll see if i can. (NB/ my arthemetric might be a bit out on the
offset values. i was a bit drunk when writing this...if i don't make
sense, just send me the section you don't understand):

it is recommended that you read FUNK.WRI (which you will find with
the distribution) as it explains the "big picture". Funktracker is
a "dual piped" format that can perform duel command effects on a
single channel. this is a very valuable feature. i still haven't
seen any trackers that can do this, and it is a real space saver.
funtracker is designed for efficiency and speed. i designed it for
the express purpose of PC +386 Pmode demos. it is designed to cater 
for a whole range of cards but namely DAC cards (ie SoundBlaster,
PAS16 and AWE32) in mind.

unlike most other formats, funktracker data is organised in intel
word covention. Unlike MODs where you can to convert each word (which is
natural. it's for amiga computers).

so, if you had a byte in memory (or on file as)..

00001111 (double)

then is would look like EAX = 11110000 in the registers. This shouldn't
be new to anyone really?.

FUNKTRACKER HEADER
------------------

sig       0 | 4 | preamble set to "Funk"
info      4 : 4 | this word contains the following packed info:


0 0 0 0 0 0 0 0   1 1 1 1 1 1 1 1   2 2 2 2 2 2 2 2   3 3 3 3 3 3 3 3
\-day---/ \month--/ \----year---/   \-card/ \-CPU-/   | 0 0 0 0 0 0 0
                                                      | \memory reqi/
                                                      |    (256Kb x)
                                       16 bit = 1 ----

(NB/ the appearance is as if you see it in a sector editor...Least
significant bits first to most significant bits... which is in
INTEL format anyways. unless you have some other computer like a SUN
or a DEC, you can easyerly extract each value with some AND's and SHR's).

cpu:  0 = Unknown
      1 = IBM ????
      2 = IBM ????
      3 = Intel386
      4 = Intel486
      5 = Pentium
card:
      0 = SB 2.0
      1 = SB PRO
      2 = GUS v<>
      3 = SB Compatable
      4 = SB 16
      5 = GUS f<>
      6 = Ripped/converted from another format
      7 = Pro Audio

  is in summary it tells you the date the file was created, the card and
  cpu it was created on, and the memory requirements the song needs.

  NB/ if this is confusing you then don't worry about it. it's not
  essential to extract info from here inorder to play it. it's purpose
  is purely statistical.

LZH_check_size   8 : 4 | this is the file size. if you load a song that's
                         size thats different from this number, then you
                         know it is corrupt in some way. it would be
                         highly recommended not to play it.

LZH_check_sum    12 | 4 | This field (pre-release versions 1.04 a below
                          was used as a provisional 4 byte checksum field.
                          Now it is used for FNK charactristics:

 Format: - "Fk**" for fixed channeling or
           "Fv**" for variable channeling

 The ** is a dec number ranging from 0 to 99. For example, if the song is
 a 32 channel module, then the preamble is "Fk32". 10 Channels is "Fk10".

 if you see garble in this field, then you know it was created on a < 1.05
 editor. you can safely assume that this is a 8 channel, fixed channel
 module.

loop_order      13  | 1 | if this field is set to 0ffh, then the song won't
                          loop back. That is, when it has finished playing
                          the last pattern in the order list, it will stop.

                          if the value is anything other than this (0 - 7fh),
                          then the tracker will loop back to order number in
                          this field and commence playing the patterns at
                          that order number.


order_list      14  | 256 | this is the order_list. pretty much the same as
                            any other trackers order list (aka sequence list).
                            this table contains a list of pattern numbers
                            to be played in a given order.

break_list      270 | 128 | the break list is like the 669 break list (this
                            concept was stollen from the 669 format). A break
                            order is a value that tells the tracker to stop
                            playing a pattern when it reaches a given line
                            number in the pattern. When is reaches it, it
                            will then proceed to the next pattern in the
                            order list.
                            In the table we have 128 break numbers of each of
                            the 128 possible patterns (all respectively
                            ordered).


SAMPLE BLOCK DATA
-----------------

after the header, we then have our 64 sample entries stored. each sample
record/set is 32 bytes. you can calc each one with a simple EAX SHL 5:

sname       (SAMPLE NUMBER * 32) + 398 | 19| sample name (19 bytes)
start       (SAMPLE NUMBER * 32) + 402 | 4 | sample loop start pointer (in units)
length      (SAMPLE NUMBER * 32) + 406 | 4 | lenght (in units) of sample
volume      (SAMPLE NUMBER * 32) + 407 | 1 | 0->255
balance     (SAMPLE NUMBER * 32) + 408 | 1 | 00 <- 80 -> FF
pt_and_sop  (SAMPLE NUMBER * 32) + 409 | 1 | port type & Sample offs shifter


MS              LS

 7 6 5 4 3 2 1 0

 \...../ \...../
  port    sample
  type     offs factor  (see FUNK.WRI)

vv_waveform (SAMPLE NUMBER * 32) + 410 | 1 | Vibrito Waveform & Tremolo waveform

MS              LS

 7 6 5 4 3 2 1 0

 \...../ \...../
  vibrato tremola
  WF       WF  (see FUNK.WRI)

rl_and_as   (SAMPLE NUMBER * 32) + 411 | 1 | Retrig number & arpeggio speed

MS              LS

 7 6 5 4 3 2 1 0

 \...../ \...../
  retrig  arpeggio
  no      speed (see FUNK.WRI)



Pattern Data
=-=-=-=-=-=-

Each pattern block is 600h bytes - 8 by 64 slot. Each slot has
the following format:

 00000000 11111111 22222222
 \    /\     /\  / \      /
  note  sample com  command value

 - if note:  = 3D, then reload sample attrs
             = 3F, then it's a null slot
             = 3E, then sample only slot


basically, it's the same as the 669 format accept you have 3
additional/different note values:

3E, then sample only slot
-------------------------

if the 1st byte is this value, then it's a "sample only" slot.
play the slot at the last note played (in the chan_info). decode
the sample and commands and active them. etc.

3F, then it's a null slot
-------------------------

this means..null slot. only commands can be used with these slots.
no sample or note processing is preformed.... basically a "blank"
slot.

3D, then reload sample attrs
----------------------------

when the tracker see's one of these, it will decode the sample
as normal... it will "reuse" the following attributes from the
last sample (block) played:

volume      (SAMPLE NUMBER * 32) + 407 | 1 | 0->255
balance     (SAMPLE NUMBER * 32) + 408 | 1 | 00 <- 80 -> FF
pt_and_sop  (SAMPLE NUMBER * 32) + 409 | 1 | port type & Sample offs shifter
vv_waveform (SAMPLE NUMBER * 32) + 410 | 1 | Vibrito Waveform & Tremolo waveform
rl_and_as   (SAMPLE NUMBER * 32) + 411 | 1 | Retrig number & arpeggio speed


Commands
--------

 Full Commands                              Command 'O'

 A  :Frequency Port Up                      O00:Vibrato Sine
 B  :Frequency Port Dn                      O01:Vibrato Triangle
 C  :Frequency Porta                        O02:Vibrato Square
 D  :Frequency Vibrato                      O03:Vibrato Sawtooth
 E  :Freq Vibrato Fanin                     O04:Vibrato Random
 F  :Freq Vibrato Fanout                    O05:tremola Sine
 G  :Volume Sld Up                          O06:tremola Triangle
 H  :Volume Slide Down                      O07:tremola Square
 I  :Volume Porta                           O08:tremola Sawtooth
 J  :Volume Reverb                          O09:tremola Random
 K  :Tremola                                O0A:Halt Note System
 L  :Arpeggio                               O0B:Halt Volume System
 M  :Sample Offset                          O0C:Halt All Systems
 N  :Volume                                 O0D:Invert Funkcrtl
                                            O0E:Snap to log Porting
                                            O0F:Snap to Line Porting
                                            O1 :Volume Cut!
                                            O2 :Real Frequency Adjust
                                            O3 :Set Arpeggio Speed
                                            O4 :Fine Port Up
                                            O5 :Fine Port Dn
                                            O6 :Fine Volume Slide Up
                                            O7 :Fine Volume Slide Dn
                                            O8 :Volume Crest
                                            O9 :Volume Trough
                                            OA :Set Master Volume
                                            OB :Expand Loop
                                            OC :Colapse Loop
                                            OD :Note Retrig
                                            OE :Set Channel Balance
                                            OF :Tempo


for a detailed description of the commands, refer to the FUNK.WRI file.
