home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / loaders / load_mtm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  6.4 KB  |  277 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This library is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU Library General Public License as
  6.     published by the Free Software Foundation; either version 2 of
  7.     the License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Library General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Library General Public
  15.     License along with this library; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: load_mtm.c,v 1.17 1998/12/07 06:00:19 miod Exp $
  22.  
  23.   MTM module loader
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #include <string.h>
  32.  
  33. #include <mikmod_internals.h>
  34.  
  35. /*========== Module structure */
  36.  
  37. typedef struct MTMHEADER {
  38.     UBYTE id[3];            /* MTM file marker */
  39.     UBYTE version;            /* upper major, lower nibble minor version number */
  40.     CHAR  songname[20];        /* ASCIIZ songname */
  41.     UWORD numtracks;        /* number of tracks saved */
  42.     UBYTE lastpattern;        /* last pattern number saved */
  43.     UBYTE lastorder;        /* last order number to play (songlength-1) */
  44.     UWORD commentsize;        /* length of comment field */
  45.     UBYTE numsamples;        /* number of samples saved  */
  46.     UBYTE attribute;        /* attribute byte (unused) */
  47.     UBYTE beatspertrack;
  48.     UBYTE numchannels;        /* number of channels used  */
  49.     UBYTE panpos[32];        /* voice pan positions */
  50. } MTMHEADER;
  51.  
  52. typedef struct MTMSAMPLE {
  53.     CHAR  samplename[22];
  54.     ULONG length;
  55.     ULONG reppos;
  56.     ULONG repend;
  57.     UBYTE finetune;
  58.     UBYTE volume;
  59.     UBYTE attribute;
  60. } MTMSAMPLE;
  61.  
  62. typedef struct MTMNOTE {
  63.     UBYTE a,b,c;
  64. } MTMNOTE;
  65.  
  66. /*========== Loader variables */
  67.  
  68. static MTMHEADER *mh = NULL;
  69. static MTMNOTE *mtmtrk = NULL;
  70. static UWORD pat[32];
  71.  
  72. CHAR MTM_Version[] = "MTM";
  73.  
  74. /*========== Loader code */
  75.  
  76. BOOL MTM_Test(void)
  77. {
  78.     UBYTE id[3];
  79.  
  80.     if(!_mm_read_UBYTES(id,3,modfp)) return 0;
  81.     if(!memcmp(id,"MTM",3)) return 1;
  82.     return 0;
  83. }
  84.  
  85. BOOL MTM_Init(void)
  86. {
  87.     if(!(mtmtrk=(MTMNOTE*)_mm_calloc(64,sizeof(MTMNOTE)))) return 0;
  88.     if(!(mh=(MTMHEADER*)_mm_malloc(sizeof(MTMHEADER)))) return 0;
  89.  
  90.     return 1;
  91. }
  92.  
  93. void MTM_Cleanup(void)
  94. {
  95.     if(mtmtrk) free(mtmtrk);
  96.     if(mh) free(mh);
  97.  
  98.     mtmtrk = NULL;
  99.     mh = NULL;
  100. }
  101.  
  102. UBYTE* MTM_Convert(void)
  103. {
  104.     int t;
  105.     UBYTE a,b,inst,note,eff,dat;
  106.  
  107.     UniReset();
  108.     for(t=0;t<64;t++) {
  109.         a=mtmtrk[t].a;
  110.         b=mtmtrk[t].b;
  111.         inst=((a&0x3)<<4)|(b>>4);
  112.         note=a>>2;
  113.         eff=b&0xf;
  114.         dat=mtmtrk[t].c;
  115.  
  116.         if(inst) UniInstrument(inst-1);
  117.         if(note) UniNote(note+2*OCTAVE);
  118.  
  119.         /* MTM bug workaround : when the effect is volslide, slide-up *always*
  120.            overrides slide-down. */
  121.         if(eff==0xa && (dat&0xf0)) dat&=0xf0;
  122.  
  123.         /* Convert pattern jump from Dec to Hex */
  124.         if(eff==0xd)
  125.             dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
  126.         /* finetune conversion to Lxx */
  127.         if(eff==5)
  128.             S3MIT_ProcessCmd(0xc,dat,1);
  129.         else
  130.             UniPTEffect(eff,dat);
  131.         UniNewline();
  132.     }
  133.     return UniDup();
  134. }
  135.  
  136. BOOL MTM_Load(BOOL curious)
  137. {
  138.     int t,u;
  139.     MTMSAMPLE s;
  140.     SAMPLE *q;
  141.  
  142.     /* try to read module header  */
  143.     _mm_read_UBYTES(mh->id,3,modfp);
  144.     mh->version     =_mm_read_UBYTE(modfp);
  145.     _mm_read_string(mh->songname,20,modfp);
  146.     mh->numtracks   =_mm_read_I_UWORD(modfp);
  147.     mh->lastpattern =_mm_read_UBYTE(modfp);
  148.     mh->lastorder   =_mm_read_UBYTE(modfp);
  149.     mh->commentsize =_mm_read_I_UWORD(modfp);
  150.     mh->numsamples  =_mm_read_UBYTE(modfp);
  151.     mh->attribute   =_mm_read_UBYTE(modfp);
  152.     mh->beatspertrack=_mm_read_UBYTE(modfp);
  153.     mh->numchannels =_mm_read_UBYTE(modfp);
  154.     _mm_read_UBYTES(mh->panpos,32,modfp);
  155.  
  156.     if(feof(modfp)) {
  157.         _mm_errno = MMERR_LOADING_HEADER;
  158.         return 0;
  159.     }
  160.  
  161.     /* set module variables */
  162.     of.initspeed = 6;
  163.     of.inittempo = 125;
  164.     of.modtype   = strdup(MTM_Version);
  165.     of.numchn    = mh->numchannels;
  166.     of.numtrk    = mh->numtracks+1;         /* get number of channels */
  167.     of.songname  = DupStr(mh->songname,20); /* make a cstr of songname */
  168.     of.numpos    = mh->lastorder+1;         /* copy the songlength */
  169.     of.numpat    = mh->lastpattern+1;
  170.     of.reppos    = 0;
  171.     for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<< 4;
  172.     of.numins=of.numsmp=mh->numsamples;
  173.  
  174.     if(!AllocSamples()) return 0;
  175.     q=of.samples;
  176.     for(t=0;t<of.numins;t++) {
  177.         /* try to read sample info */
  178.         _mm_read_string(s.samplename,22,modfp);
  179.         s.length    =_mm_read_I_ULONG(modfp);
  180.         s.reppos    =_mm_read_I_ULONG(modfp);
  181.         s.repend    =_mm_read_I_ULONG(modfp);
  182.         s.finetune  =_mm_read_UBYTE(modfp);
  183.         s.volume    =_mm_read_UBYTE(modfp);
  184.         s.attribute =_mm_read_UBYTE(modfp);
  185.  
  186.         if(feof(modfp)) {
  187.             _mm_errno = MMERR_LOADING_SAMPLEINFO; 
  188.             return 0;
  189.         }
  190.  
  191.         q->samplename = DupStr(s.samplename,22);
  192.         q->seekpos   = 0;
  193.         q->speed     = finetune[s.finetune];
  194.         q->length    = s.length;
  195.         q->loopstart = s.reppos;
  196.         q->loopend   = s.repend;
  197.         q->volume    = s.volume;
  198.         if((s.repend-s.reppos)>2) q->flags |= SF_LOOP;
  199.  
  200.         if(s.attribute&1) {
  201.             /* If the sample is 16-bits, convert the length and replen
  202.                byte-values into sample-values */
  203.             q->flags|=SF_16BITS;
  204.             q->length>>=1;
  205.             q->loopstart>>=1;
  206.             q->loopend>>=1;
  207.         }
  208.  
  209.         q++;
  210.     }
  211.  
  212.     if(!AllocPositions(of.numpos)) return 0;
  213.     for(t=0;t<of.numpos;t++)
  214.         of.positions[t]=_mm_read_UBYTE(modfp);
  215.     for(;t<128;t++) _mm_read_UBYTE(modfp);
  216.     if(feof(modfp)) {
  217.         _mm_errno = MMERR_LOADING_HEADER;
  218.         return 0;
  219.     }
  220.  
  221.     if(!AllocTracks()) return 0;
  222.     if(!AllocPatterns()) return 0;
  223.  
  224.     of.tracks[0]=MTM_Convert();        /* track 0 is empty */
  225.     for(t=1;t<of.numtrk;t++) {
  226.         int s;
  227.  
  228.         for(s=0;s<64;s++) {
  229.             mtmtrk[s].a=_mm_read_UBYTE(modfp);
  230.             mtmtrk[s].b=_mm_read_UBYTE(modfp);
  231.             mtmtrk[s].c=_mm_read_UBYTE(modfp);
  232.         }
  233.  
  234.         if(feof(modfp)) {
  235.             _mm_errno = MMERR_LOADING_TRACK;
  236.             return 0;
  237.         }
  238.  
  239.         if(!(of.tracks[t]=MTM_Convert())) return 0;
  240.     }
  241.  
  242.     for(t=0;t<of.numpat;t++) {
  243.         _mm_read_I_UWORDS(pat,32,modfp);
  244.         for(u=0;u<of.numchn;u++)
  245.             of.patterns[((long)t*of.numchn)+u]=pat[u];
  246.     }
  247.  
  248.     /* read comment field */
  249.     if(mh->commentsize)
  250.         if(!ReadLinedComment(mh->commentsize/40,40)) return 0;
  251.  
  252.     return 1;
  253. }
  254.  
  255. CHAR *MTM_LoadTitle(void)
  256. {
  257.     CHAR s[20];
  258.  
  259.     _mm_fseek(modfp,4,SEEK_SET);
  260.     if(!fread(s,20,1,modfp)) return NULL;
  261.  
  262.     return(DupStr(s,20));
  263. }
  264.  
  265. /*========== Loader information */
  266.  
  267. MLOADER load_mtm={
  268.     NULL,
  269.     "MTM",
  270.     "MTM loader v1.0",
  271.     MTM_Init,
  272.     MTM_Test,
  273.     MTM_Load,
  274.     MTM_Cleanup,
  275.     MTM_LoadTitle
  276. };
  277.