home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 February / PCWorld_2000-02_cd.bin / Software / Servis / FFE / MOD.SWG / 0038_MED.pas < prev    next >
Pascal/Delphi Source File  |  1997-03-02  |  27KB  |  712 lines

  1. -----------------------------------------------------------------------------
  2.         MED/OctaMED MMD0 and MMD1 file formats
  3.         written by Teijo Kinnunen (25.4.1992)
  4.         Revision 1
  5. -----------------------------------------------------------------------------
  6.  
  7. Background
  8. ----------
  9. A  couple of years ago, when programming MED V2.1, I needed a file format for
  10. MED  modules.   The  only  "module"  format  in  MED V2.0 was the Sng+samples
  11. format.  Although it produced compact files, it was very difficult and tricky
  12. to  read  in.  Therefore, I designed a new file format, that would be easy to
  13. use  in  module  player programs etc.  This file format was named 'MMD0' (Med
  14. MoDule  0).   The  limitations in MMD0 block format forced me to create a new
  15. file format for OctaMED Professional, this format is 'MMD1'.  It's mostly the
  16. same  as  MMD0, except the block structure is different.  At the time of this
  17. writing  (when  OctaMED  Pro is not even released yet), MMD0's are absolutely
  18. more common than MMD1's.
  19.  
  20. Design concepts
  21. ---------------
  22. One  of  the  main  goals  was  to  make MMD's (MED modules) as extensible as
  23. possible.   This  would  have  been  easy to implement with IFF-style chunks.
  24. However, this method is obviously not the best for play-routine use.
  25.  
  26. Therefore, MMD's are implemented in quite an extraordinary way.  They consist
  27. of  structures  (similar  to  C  structs),  and  pointers.  In a module file,
  28. pointers  are defined as offsets from the beginning of the module.  This way,
  29. a  particular  structure  can be read just by Seek()'ing using the pointer as
  30. the  offset from the beginning of the file.  When a module has been read into
  31. memory,  it has to be relocated before it can be used (the relocation is done
  32. simply by adding the address of the module to the pointers).
  33.  
  34. As  with  the  Amiga  OS,  a  MMD  file  does not contain absolute addresses.
  35. There's  a  module  header  structure  at  the  beginning  of the file.  This
  36. structure contains pointers to different parts of the module.  And you *MUST*
  37. use  these pointers.  You may NOT expect that the song structure is at offset
  38. $00000034,  for  example.   Although it usually is, this may change in future
  39. releases.   In  addition,  it's  possible that a structure even doesn't exist
  40. (the  structure  pointer is NULL).  Therefore, you *MUST* check the structure
  41. pointer  before  accessing  the  structure.   Finally, when writing MMD's you
  42. *MUST*  set  undefined/reserved  fields  to  zeros.  More finally, you *MUST*
  43. align  all  structures  to  even  boundaries!  (I forgot the alignment in MED
  44. V3.00 save routine, resulting Guruing modules under some conditions :-(
  45.  
  46. The module header
  47. -----------------
  48. This  structure must exist at the beginning of each MED module file.  Each of
  49. the structure members are described below.
  50.  
  51. In  multi-modules,  there  are header structs for each song.  (The subsequent
  52. header  pointers  can  be found from expdata structure.  Multi-modules should
  53. have  the  same  smplarr  pointer  in  every  header.) Older MEDs which don't
  54. recognize  multi-modules  consider a multi-module as an ordinary module (only
  55. the first song is loaded).
  56.  
  57. The numbers enclosed in /* */ at the beginning of each line are (decimal)
  58. offsets of each member (for assembly programmers).
  59.  
  60. -----------------------------------------------------------------------------
  61. struct MMD0 {
  62. /* 0 */     ULONG   id;
  63. /* 4 */     ULONG   modlen;
  64. /* 8 */     struct MMD0song *song;
  65. /* 12 */    ULONG   reserved0;
  66. /* 16 */    struct MMD0Block **blockarr;
  67. /* 20 */    ULONG   reserved1;
  68. /* 24 */    struct InstrHdr **smplarr;
  69. /* 28 */    ULONG   reserved2;
  70. /* 32 */    struct MMD0exp *expdata;
  71. /* 36 */    ULONG   reserved3;
  72. /* 40 */    UWORD   pstate;  /* some data for the player routine */
  73. /* 42 */    UWORD   pblock;
  74. /* 44 */    UWORD   pline;
  75. /* 46 */    UWORD   pseqnum;
  76. /* 48 */    WORD    actplayline;
  77. /* 50 */    UBYTE   counter;
  78. /* 51 */    UBYTE   extra_songs; /* number of songs - 1 */
  79. }; /* length = 52 bytes */
  80.  
  81. -----------------------------------------------------------------------------
  82. id
  83. --
  84. This longword is used to identify the MMD and its version.  Currently defined
  85. MMD  types are MMD0 (0x4D4D4430) and MMD1 (0x4D4D4431).  MMD2 and upwards are
  86. reserved for future versions.
  87.  
  88. In  multi-modules,  the  following  modules usually contain id MCNT, or MCN1.
  89. The first module always has MMD0 or MMD1 as an id.
  90.  
  91. modlen
  92. ------
  93. This longword contains the length of the entire module.
  94.  
  95. song
  96. ----
  97. Pointer to a MMD0song structure. This structure MUST ALWAYS EXIST!
  98.  
  99. blockarr
  100. --------
  101. Pointer to a table of block pointers. For example:
  102.     blockarr:  $00003000
  103.             block 0 ptr block 1 ptr block 2 ptr
  104. offset  $00003000:  $00002000,  $00002400,  $00002800 ....
  105.  
  106. offset  $00002000: block 0 data...
  107. offset  $00002400: block 1 data...
  108. ..
  109. The size of the table is MMD0song.numblocks longwords.
  110.  
  111. smplarr
  112. -------
  113. Pointer to a table of instrument pointers. The size of the table is
  114. MMD0song.songlen longwords. This pointer is zero in OctaMED Pro MMD1 songs.
  115. In this case, OctaMED Pro loads the instruments from disk(s).
  116.  
  117. expdata
  118. -------
  119. Pointer to an expansion structure.  The expansion structure contains a lot of
  120. extra  information.   The  exp.   structure does not exist in all MMD's.  (Be
  121. sure to check the pointer before using it.)
  122.  
  123. pstate, pblock, pline, pseqnum, actplayline, counter
  124. ----------------------------------------------------
  125. These  are  variables for the play routine.  You can read these fields to get
  126. the  current  song  position  (not all versions of the play routine use these
  127. fields,  however).   When writing a MMD, you should leave all fields to zero,
  128. except the 'actplayline', which ought to be -1 ($FFFF).
  129.  
  130. extra_songs
  131. -----------
  132. This  field  contains  the  number  of  songs  in  the  current  module.  For
  133. non-multi-modules,  this  is 0.  If there are two songs, extra_songs contains
  134. 1, and so on.
  135.  
  136. reserved0,1,2,3
  137. ---------------
  138. Not currently defined. Set to zero.
  139.  
  140.  
  141. The song structure (MMD0song)
  142. -----------------------------
  143. This  structure contains the basic information about the song.  It must exist
  144. on every module file.
  145.  
  146. -----------------------------------------------------------------------------
  147. struct MMD0song {
  148.     struct MMD0sample sample[63];   /* 63 * 8 bytes = 504 bytes */
  149.     UWORD   numblocks;      /* offs: 504 */
  150.     UWORD   songlen;        /* offs: 506 */
  151.     UBYTE   playseq[256];       /* offs: 508 */
  152.     UWORD   deftempo;       /* offs: 764 */
  153.     BYTE    playtransp;     /* offs: 766 */
  154.     UBYTE   flags;          /* offs: 767 */
  155.     UBYTE   flags2;         /* offs: 768 */
  156.     UBYTE   tempo2;         /* offs: 769 */
  157.     UBYTE   trkvol[16];     /* offs: 770 */
  158.     UBYTE   mastervol;      /* offs: 786 */
  159.     UBYTE   numsamples;     /* offs: 787 */
  160. }; /* length = 788 bytes */
  161.  
  162. -----------------------------------------------------------------------------
  163. sample
  164. ------
  165. Contains some basic info about each sample. The structure looks like this:
  166.  
  167. -----------------------------------------------------------------------------
  168.     struct MMD0sample {
  169.         UWORD rep,replen;   /* offs: 0(s), 2(s) */
  170.         UBYTE midich;       /* offs: 4(s) */
  171.         UBYTE midipreset;   /* offs: 5(s) */
  172.         UBYTE svol;     /* offs: 6(s) */
  173.         BYTE strans;        /* offs: 7(s) */
  174.     };
  175.  
  176. -----------------------------------------------------------------------------
  177.     rep     repeat start offset, shifted right one bit (as in
  178.             Protracker).
  179.     replen      repeat length, shifted right one bit.
  180.     midich      MIDI channel for current instrument, 0 if not MIDI.
  181.     midipreset  MIDI preset number for current instrument, 0 if no
  182.             preset.
  183.     svol        default volume for current instrument (0 - 64).
  184.     strans      instrument transpose value.
  185.  
  186. More information is defined in expdata structure.
  187.  
  188. numblocks
  189. ---------
  190. Number  of  blocks  in current song.  This field also indicates the length of
  191. the blockarr table in longwords.
  192.  
  193. songlen
  194. -------
  195. Song length (number of sequence numbers in the play sequence list).
  196.  
  197. playseq
  198. -------
  199. This is the play sequence list.
  200.  
  201. deftempo
  202. --------
  203. Default  song  tempo (the leftmost tempo slider in MED/OctaMED).  If BPM mode
  204. is on, this value indicates BPM.
  205.  
  206. playtransp
  207. ----------
  208. The global play transpose value for current song.
  209.  
  210. flags
  211. -----
  212. Contains many single-bit flags:
  213.     FLAG_FILTERON   0x1 the hardware audio filter is on
  214.     FLAG_JUMPINGON  0x2 mouse pointer jumping on (not in OctaMED Pro)
  215.     FLAG_JUMP8TH    0x4 jump every 8th line (not in OctaMED Pro)
  216.     FLAG_INSTRSATT  0x8     sng+samples indicator (not useful in MMD's)
  217.     FLAG_VOLHEX 0x10    volumes are HEX
  218.     FLAG_STSLIDE    0x20    use ST/NT/PT compatible sliding
  219.     FLAG_8CHANNEL   0x40    this is OctaMED 5-8 channel song
  220.  
  221.     (bit 0x80 is not defined, and must be set to zero)
  222.  
  223. flags2
  224. ------
  225. More flags, currently only BPM stuff:
  226.     FLAG2_BMASK 0x1F (bits 0-4)     BPM beat length (in lines)
  227.                         0 = 1 line, $1F = 32 lines.
  228.                     (The rightmost slider in OctaMED Pro
  229.                      BPM mode.)
  230.     FLAG2_BPM   0x20    BPM mode on
  231.  
  232.     (bits 0x40 and 0x80 are not defined, and must be set to zero)
  233.  
  234. tempo2
  235. ------
  236. This is the "secondary tempo" (the rightmost MED/OctaMED tempo slider),
  237. indicating the number of timing pulses per line.
  238.  
  239. trkvol[16]
  240. ----------
  241. The relative track volumes (1 - 64) for each track.
  242.  
  243. mastervol
  244. ---------
  245. The relative master volume (1 - 64).
  246.  
  247. numsamples
  248. ----------
  249. Number  of instruments (samples/synthsounds) in current song.  Also indicates
  250. the size of the smplarr table in longwords.
  251.  
  252.  
  253. The block format
  254. ----------------
  255. As  described above, MMD0 header structure contains a pointer (blockarr) to a
  256. table of block pointers.  These block pointers point to the actual block data
  257. structures.  The format of these data structures differ in MMD0 and MMD1 file
  258. formats.
  259.  
  260. MMD0 block format
  261. -----------------
  262. At the beginning of each block, there's a small header:
  263.  
  264. -----------------------------------------------------------------------------
  265.     struct MMD0Block {
  266.         UBYTE numtracks,lines;
  267.     };
  268.  
  269. -----------------------------------------------------------------------------
  270.     numtracks   number of tracks (4, 8, 12 or 16) on this block
  271.     lines       number of lines on this block; 0 = 1 line,
  272.             255 = 256 lines
  273.  
  274. Following  this  header,  there is the actual note data, consisting of 3-byte
  275. structures  containing  a  note  and  its  command.   The  data  is  arranged
  276. sequentially a line at a time, i.e. in the following order:
  277.     line 0 track 0
  278.     line 0 track 1
  279.     line 0 track 2
  280.     line 0 track 3
  281.     line 1 track 0
  282.     line 1 track 1
  283.     ...
  284. The 3-byte structure looks like this (each letter corresponds to one bit):
  285.  
  286.     xynnnnnn iiiicccc dddddddd
  287.  
  288.     n = note number (0 - $3F). 0 = ---, 1 = C-1, 2 = C#1...
  289.     i = the low 4 bits of the instrument number
  290.     x = the 5th bit (#4) of the instrument number
  291.     y = the 6th bit (#5) of the instrument number
  292.     c = command number (0 - $F)
  293.     d = databyte ($00 - $FF)
  294.  
  295. MMD1 block format
  296. -----------------
  297. MMD1  block format can contain a lot more information than MMD0's.  The block
  298. header looks like this:
  299.  
  300. -----------------------------------------------------------------------------
  301.     struct MMD1Block {
  302.         UWORD numtracks;
  303.         UWORD lines;
  304.         struct BlockInfo *info;
  305.     };
  306.  
  307. -----------------------------------------------------------------------------
  308.     numtracks   Number of tracks in this block (4, 8, 12, or 16).
  309.     lines       Number of lines in this block (0 = 1 line etc.).
  310.             OctaMED Pro can handle upto 3200 lines/block, so
  311.             this is obviously the practical upper limit.
  312.     info        Pointer to structure containing extra information.
  313.             (Can be NULL, if no BlockInfo struct exists).
  314.  
  315.     The BlockInfo structure is:
  316.  
  317. -----------------------------------------------------------------------------
  318.     struct BlockInfo {
  319.         ULONG   *hlmask;
  320.         UBYTE   *blockname;
  321.         ULONG   blocknamelen;
  322.         ULONG   reserved[6];
  323.     };
  324.  
  325. -----------------------------------------------------------------------------
  326.     hlmask      Pointer to an array of longwords, containing info
  327.             about line highlighting (TAB key on MED). The number
  328.             of longwords depend on the number of lines on the
  329.             block. (E.g: 1 line -> 1 longword, 32 lines -> 1 lw,
  330.             33 lines -> 2 lws, 256 lines -> 4 lws)
  331.             The bits in the longwords are arranged in reversed
  332.             order (e.g. bit #0 = line 0, bit #31 = line 31).
  333.  
  334.     blockname   Pointer to the name of the block. Must be null-
  335.             terminated.
  336.  
  337.     blocknamelen    Length of the block name, including the terminating
  338.             zero. OctaMED Pro currently has the maximum length of
  339.             41 chars (+ zero). However, this may change in the
  340.             future. Don't read blocknames longer than you are
  341.             able to handle!
  342.  
  343.     reserved[6] These are reserved for future extensions. Must be set
  344.             to zero.
  345.  
  346.     The note structures, which are 4 bytes long in MMD1 modules, are
  347.     arranged exactly as in MMD0 modules.
  348.  
  349.         xnnnnnnn xxiiiiii cccccccc dddddddd
  350.  
  351.     n = note number (0 - $7F, 0 = ---, 1 = C-1...)
  352.     i = instrument number (0 - $3F)
  353.     c = command ($00 - $FF)
  354.     d = databyte ($00 - $FF)
  355.     x = undefined, reserved for future expansion. MUST BE SET TO ZERO,
  356.         AND MASKED OUT WHEN READING THE NOTE OR INSTRUMENT NUMBER.
  357.  
  358.  
  359. The instrument format
  360. ---------------------
  361. The  MMD0  header  structure  contains  a  pointer  (smplarr)  to  a table of
  362. instrument  pointers.   These  pointers  point  to the actual instrument data
  363. structures.   If an instrument pointer is zero, there's no instrument in that
  364. slot.
  365.  
  366. Every  instrument  has a six-byte header structure, which is the same for all
  367. instrument types (sample/synth/hybrid).
  368.  
  369. -----------------------------------------------------------------------------
  370.     struct InstrHdr {
  371.         ULONG   length;
  372.         WORD    type;
  373.         /* Followed by actual data */
  374.     };
  375.  
  376. -----------------------------------------------------------------------------
  377.     length      indicates the length of the instrument (the six byte
  378.             header data length is not included)
  379.     type        instrument type - currently the following types are
  380.             defined:
  381.  
  382.         HYBRID      -2
  383.         SYNTHETIC   -1
  384.         SAMPLE      0   (an ordinary 1-octave sample)
  385.         IFF5OCT     1   (5 octaves)
  386.         IFF3OCT     2   (3 octaves)
  387.         (The following ones are recognized by OctaMED Pro only)
  388.         IFF2OCT     3   (2 octaves)
  389.         IFF4OCT     4   (4 octaves)
  390.         IFF6OCT     5   (6 octaves)
  391.         IFF7OCT     6   (7 octaves)
  392.  
  393. The sample-type instruments (>= 0) contain the actual sample data straight
  394. after the header structure.
  395.  
  396. Synthetic instruments
  397. ---------------------
  398. Synthsounds  have  a  special  structure  of  their  own.   They also contain
  399. waveforms and pointers to them.  Therefore, relocation is required.  However,
  400. there's  an  important  difference:  pointers are expressed as an offset from
  401. the  beginning  of  the  synthsound,  NOT  the  beginning of the module.  The
  402. 'reloc.a' routine provided with MED/OctaMED automatically handles this.
  403.  
  404. The synthsound structure is as follows (note that this structure contains the
  405. header structure):
  406.  
  407. -----------------------------------------------------------------------------
  408.     struct SynthInstr {
  409.         ULONG   length;     /* length of this struct */
  410.         WORD    type;       /* -1 or -2 (offs: 4) */
  411.         UBYTE   defaultdecay;
  412.         UBYTE   reserved[3];
  413.         UWORD   rep;
  414.         UWORD   replen;
  415.         UWORD   voltbllen;  /* offs: 14 */
  416.         UWORD   wftbllen;   /* offs: 16 */
  417.         UBYTE   volspeed;   /* offs: 18 */
  418.         UBYTE   wfspeed;    /* offs: 19 */
  419.         UWORD   wforms;     /* offs: 20 */
  420.         UBYTE   voltbl[128];    /* offs: 22 */
  421.         UBYTE   wftbl[128]; /* offs: 150 */
  422.         struct  SynthWF *wf[64]; /* offs: 278 */
  423.     };
  424.  
  425. -----------------------------------------------------------------------------
  426.     defaultdecay    = the default decay of the current synthsound. This
  427.               is NOT used in modules. It's significant only when
  428.               saving a single synthsound.
  429.  
  430.     reserved[3] = set to zero.
  431.  
  432.     rep, replen = repeat/rep. length for hybrid sounds. Used only
  433.               when saving a single hybrid sound.
  434.  
  435.     voltbllen   = the length of the volume sequence table.
  436.  
  437.     wftbllen    = the length of the waveform sequence table.
  438.  
  439.     volspeed    = the initial volume table execution speed.
  440.  
  441.     wfspeed     = the initial waveform table execution speed.
  442.  
  443.     wforms      = the number of waveforms in the current synthsound.
  444.  
  445.     voltbl      = the actual volume sequence table. Values $00-$7F
  446.               are volumes or command arguments. Values >= $80 are
  447.               commands. The following commands are currently
  448.               defined:
  449.                 $FF END     $F4 EN1
  450.                 $FE JMP     $F3 CHU
  451.                 $FB HLT     $F2 CHD
  452.                 $FA JWS     $F1 WAI
  453.                 $F6 EST     $F0 SPD
  454.                 $F5 EN2
  455.  
  456.     wftbl       = the actual waveform sequence table. Values $00-$7F
  457.               are waveform numbers  or command arguments. Values
  458.               >= $80 are commands. The following commands are
  459.               currently defined:
  460.                 $FF END     $F6 RES
  461.                 $FE JMP     $F5 VBS
  462.                 $FD ARE     $F4 VBD
  463.                 $FC ARP     $F3 CHU
  464.                 $FB HLT     $F2 CHD
  465.                 $FA JVS     $F1 WAI
  466.                 $F7 VWF     $F0 SPD
  467.  
  468.     wf      = pointers to waveforms. (Once again: relative to the
  469.               beginning of the synthsound!) A waveform structure
  470.               is as follows:
  471.  
  472.                 struct SynthWF {
  473.                     UWORD length;   /* length in words */
  474.                     BYTE  wfdata[xx]; /* the waveform */
  475.                 };
  476.  
  477.                 (where xx = length in bytes)
  478.  
  479.               In hybrid sounds, however, wf[0] is different.
  480.  
  481. Hybrid instruments
  482. ------------------
  483. Hybrid  sounds  use  the same structure as synthsounds, except that the first
  484. waveform  (wf[0])  pointer  points to a sample.  (The sample header structure
  485. exists, as usual.)
  486.  
  487.  
  488. MMD0exp - the key to future expansions
  489. --------------------------------------
  490. For  possible  future  expansions,  I  designed  a structure for carrying the
  491. miscellaneous things that were added to MED/OctaMED now and then.  (MED V3.00
  492. was the first version, which wrote this structure.) Most of its fields are in
  493. use  now,  but it's possible to even expand this structure (things will get a
  494. bit more tricky, though).
  495.  
  496. In multi-modules, you should extract all data from the expansion structure of
  497. the  first  song.   The  only  exceptions  are  currently  the  'nextmod' and
  498. 'songname' fields, which are song-specific.
  499.  
  500. Also,  there  has  been  need  for  extending the MMD0sample structure.  Both
  501. InstrExt  and  MMDInstrInfo  provide extra information about the instruments.
  502. These  are  defined as structure arrays (exp_smp and iinfo point to the first
  503. structure).  The extension structures don't have a constant size, instead you
  504. have  to  read s_ext_entrsz or i_ext_entrsz to get the structure sizes.  When
  505. reading,  you  have to check the entrsz fields to see which structure members
  506. do exist.
  507.  
  508. The  difference  between  InstrExt and MMDInstrInfo is that InstrExt contains
  509. information the play-routine is interested in (e.g.  finetune).  MMDInstrInfo
  510. contains  "secondary"  information,  which is of no use to the player routine
  511. (e.g.  instrument name).
  512.  
  513. The expansion structure follows:
  514.  
  515. -----------------------------------------------------------------------------
  516.     struct MMD0exp {
  517.         struct MMD0 *nextmod;
  518.         struct InstrExt *exp_smp;
  519.         UWORD  s_ext_entries;
  520.         UWORD  s_ext_entrsz;
  521.         UBYTE  *annotxt;
  522.         ULONG  annolen;
  523.         struct MMDInstrInfo *iinfo;
  524.         UWORD  i_ext_entries;
  525.         UWORD  i_ext_entrsz;
  526.         ULONG  jumpmask;
  527.         UWORD  *rgbtable;
  528.         UBYTE  channelsplit[4];
  529.         struct NotationInfo *n_info;
  530.         UBYTE  *songname;
  531.         ULONG  songnamelen;
  532.         struct MMDDumpData *dumps;
  533.         ULONG  reserved2[7];
  534.     };
  535.  
  536. -----------------------------------------------------------------------------
  537.     nextmod     = pointer to the next module (or zero). (Only used in
  538.               multi-modules!)
  539.  
  540.     exp_smp     = pointer to InstrExt. Currently the first four bytes
  541.               of InstrExt have been defined:
  542.  
  543.                 struct InstrExt {
  544.                     UBYTE hold;
  545.                     UBYTE decay;
  546.                     UBYTE suppress_midi_off;
  547.                     BYTE  finetune;
  548.                 };
  549.  
  550.                 hold, decay = hold/decay values of the
  551.                           instrument
  552.  
  553.                 suppress_midi_off = 0 (FALSE) or not (TRUE)
  554.  
  555.                 finetune    = instrument finetune (-8-+7)
  556.  
  557.     s_ext_entries   = the size of InstrExt structure array (i.e. the
  558.               number of InstrExt structures).
  559.  
  560.     s_ext_entrsz    = the size of each InstrExt structure (in bytes).
  561.  
  562.     annotxt     = pointer to the annotation text (null-terminated).
  563.  
  564.     annolen     = length of 'annotxt', including the terminating \0.
  565.  
  566.     iinfo       = pointer to MMDInstrInfo. Currently the first forty
  567.               bytes have been defined:
  568.  
  569.                 struct MMDInstrInfo {
  570.                     UBYTE   name[40];
  571.                 };
  572.  
  573.                 name = null-terminated instrument name
  574.  
  575.     i_ext_entries   = the size of the MMDInstrInfo struct array (i.e. the
  576.               number of MMDInstrInfo structures).
  577.  
  578.     i_ext_entrsz    = the size of each MMDInstrInfo struct in bytes.
  579.  
  580.     jumpmask    = a mask controlling which instruments cause the
  581.               mouse pointer to jump. E.g. bit #1 = instr. #1.
  582.               This field has become obsolete in OctaMED Pro.
  583.  
  584.     rgbtable    = pointer to eight UWORDs (screen colors) to be
  585.               passed to LoadRGB4() routine.
  586.  
  587.     channelsplit    = this longword is divided to four boolean bytes,
  588.               controlling channel splitting in OctaMED 5 - 8 chnl
  589.               modes. (A non-zero byte means that the channel is
  590.               NOT splitted.) Currently only the following
  591.               combinations should be used:
  592.  
  593.               0x00000000 (8 channels (or normal 4 channel mode))
  594.               0x000000FF (7 channels)
  595.               0x0000FFFF (6 channels)
  596.               0x00FFFFFF (5 channels)
  597.  
  598.     n_info      = pointer to NotationInfo structure (used only in
  599.               OctaMED V2.0 and later). It contains some info for
  600.               the notation editor.
  601.  
  602.                 struct NotationInfo {
  603.                     UBYTE n_of_sharps;
  604.                     UBYTE flags;
  605.                     WORD  trksel[5];
  606.                     UBYTE trkshow[16];
  607.                     UBYTE trkghost[16];
  608.                     BYTE  notetr[63];
  609.                     UBYTE pad;
  610.                 };
  611.  
  612.               n_of_sharps   = number of sharps or flats (0 - 6)
  613.               flags     = misc. bits, these are defined:
  614.                         NFLG_FLAT   1
  615.                     (= use flats instead of sharps)
  616.                         NFLG_3_4    2
  617.                     (= display 12 lines instead of 16)
  618.  
  619.               trksel    = the number of the selected track,
  620.                       for each display preset
  621.                         (-1 = no track selected)
  622.  
  623.               trkshow   = tracks shown (five bits used in
  624.                       each byte, bit #0 = preset 1, etc.)
  625.  
  626.               trkghost  = tracks ghosted (as in 'trkshow')
  627.  
  628.               notetr    = note transpose value for each
  629.                       instrument (-24 - +24). If bit 6 is
  630.                       negated, the instrument is hidden.
  631.  
  632.               pad       = possibly holding info about struct
  633.                       expansions in the future. Don't
  634.                       touch!
  635.  
  636.     songname    = song name of the current song (0-terminated).
  637.               Each song of a multi-module can have a different
  638.               name.
  639.  
  640.     songnamelen = song name length (including the terminating zero).
  641.  
  642.     dumps       = MIDI dump data (created using OctaMED Pro MIDI
  643.               message editor). The 'dumps' field points to the
  644.               following struct:
  645.  
  646.                 struct MMDDumpData {
  647.                     UWORD   numdumps;
  648.                     UWORD   reserved[3];
  649.                 };
  650.  
  651.               Immediately after this struct, there are 'numdumps'
  652.               pointers to the following struct:
  653.  
  654.                 struct MMDDump {
  655.                     ULONG   length;
  656.                     UBYTE   *data;
  657.                     UWORD   ext_len;
  658.                     /* if ext_len >= 20: */
  659.                     UBYTE   name[20];
  660.                 };
  661.  
  662.               length    = length of the MIDI message dump.
  663.  
  664.               data      = pointer to the actual MIDI dump
  665.                       data.
  666.  
  667.               ext_len   = MMDDump struct extension length.
  668.                       For flexible future expansion.
  669.  
  670.               (if ext_len >= 20, the following fields exist)
  671.  
  672.               name      = name of the dump.
  673.  
  674.     reserved2   = future expansion fields, that MUST be zero now.
  675.  
  676. -----------------------------------------------------------------------------
  677. Finally, here is a collection of the most important rules you should obey
  678. when handling MMD's:
  679.  
  680.     * ALWAYS USE POINTERS, NOT ABSOLUTE OFFSETS.
  681.  
  682.     * CHECK THAT A POINTER IS NONZERO BEFORE ACCESSING ANYTHING IT
  683.       POINTS TO.
  684.  
  685.     * WHEN WRITING, SET UNDEFINED/RESERVED BITS AND BYTES TO ZERO.
  686.       WHEN READING, MASK OUT UNDEFINED BITS, AND DON'T USE UNDEFINED
  687.       FIELDS.
  688.  
  689.     * WHEN WRITING, ALWAYS ALIGN EVERYTHING TO EVEN BOUNDARIES.
  690.  
  691.     * WHEN WRITING, ALWAYS WRITE THE SONG STRUCTURE.
  692.  
  693.     * REMEMBER TO HANDLE ERROR SITUATIONS CORRECTLY (IN ALL PROGRAMS,
  694.       NOT ONLY WHEN HANDLING MMDs ;^)
  695.  
  696. If  you  don't  understand  some  part  of this file completely, try saving a
  697. module using MED, and then examine the file with a file editor.  This way you
  698. can learn easily about the file format of MED/OctaMED.
  699.  
  700. -----------------------------------------------------------------------------
  701.  
  702. I  hope this document will help programmers who wish to be able to handle
  703. modules  in  their  programs.   NOTE! This text file is PUBLIC DOMAIN. All
  704. distribution of this file,via the pd is strongly encouraged.  Thank you!
  705.  
  706.     Teijo Kinnunen
  707.     Oksantie 19
  708.     SF-86300  OULAINEN
  709.     FINLAND
  710.  
  711. ----------------------------------------------------------------------------
  712.