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_s3m.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  10.4 KB  |  428 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_s3m.c,v 1.18 1998/12/07 06:00:20 miod Exp $
  22.  
  23.   Screamtracker (S3M) 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. /* header */
  38. typedef struct S3MHEADER {
  39.     CHAR  songname[28];
  40.     UBYTE t1a;
  41.     UBYTE type;
  42.     UBYTE unused1[2];
  43.     UWORD ordnum;
  44.     UWORD insnum;
  45.     UWORD patnum;
  46.     UWORD flags;
  47.     UWORD tracker;
  48.     UWORD fileformat;
  49.     CHAR  scrm[4];
  50.     UBYTE mastervol;
  51.     UBYTE initspeed;
  52.     UBYTE inittempo;
  53.     UBYTE mastermult;
  54.     UBYTE ultraclick;
  55.     UBYTE pantable;
  56.     UBYTE unused2[8];
  57.     UWORD special;
  58.     UBYTE channels[32];
  59. } S3MHEADER;
  60.  
  61. /* sample information */
  62. typedef struct S3MSAMPLE {
  63.     UBYTE type;
  64.     CHAR  filename[12];
  65.     UBYTE memsegh;
  66.     UWORD memsegl;
  67.     ULONG length;
  68.     ULONG loopbeg;
  69.     ULONG loopend;
  70.     UBYTE volume;
  71.     UBYTE dsk;
  72.     UBYTE pack;
  73.     UBYTE flags;
  74.     ULONG c2spd;
  75.     UBYTE unused[12];
  76.     CHAR  sampname[28];
  77.     CHAR  scrs[4];
  78. } S3MSAMPLE;
  79.  
  80. typedef struct S3MNOTE {
  81.     UBYTE note,ins,vol,cmd,inf;
  82. } S3MNOTE;
  83.  
  84. typedef S3MNOTE S3MTRACK[64];
  85.  
  86. /*========== Loader variables */
  87.  
  88. static S3MNOTE   *s3mbuf  = NULL; /* pointer to a complete S3M pattern */
  89. static S3MHEADER *mh      = NULL;
  90. static UWORD     *paraptr = NULL; /* parapointer array (see S3M docs) */
  91.  
  92. CHAR* S3M_Version[2] = {
  93.     "Screamtracker x.xx",
  94.     "Imago Orpheus x.xx"
  95. };
  96.  
  97. /*========== Loader code */
  98.  
  99. BOOL S3M_Test(void)
  100. {
  101.     UBYTE id[4];
  102.  
  103.     _mm_fseek(modfp,0x2c,SEEK_SET);
  104.     if(!_mm_read_UBYTES(id,4,modfp)) return 0;
  105.     if(!memcmp(id,"SCRM",4)) return 1;
  106.     return 0;
  107. }
  108.  
  109. BOOL S3M_Init(void)
  110. {
  111.     if(!(s3mbuf=(S3MNOTE*)_mm_malloc(32*64*sizeof(S3MNOTE)))) return 0;
  112.     if(!(mh=(S3MHEADER*)_mm_malloc(sizeof(S3MHEADER)))) return 0;
  113.     if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
  114.  
  115.     return 1;
  116. }
  117.  
  118. void S3M_Cleanup(void)
  119. {
  120.     if(s3mbuf) free(s3mbuf);
  121.     if(paraptr) free(paraptr);
  122.     if(poslookup) free(poslookup);
  123.     if(mh) free(mh);
  124.  
  125.     paraptr   = NULL;
  126.     s3mbuf    = NULL;
  127.     poslookup = NULL;
  128.     mh        = NULL;
  129. }
  130.  
  131. /* Because so many s3m files have 16 channels as the set number used, but really
  132.    only use far less (usually 8 to 12 still), I had to make this function, which
  133.    determines the number of channels that are actually USED by a pattern.
  134.  
  135.    For every channel that's used, it sets the appropriate array entry of the
  136.    global variable 'remap'
  137.  
  138.    NOTE: You must first seek to the file location of the pattern before calling
  139.          this procedure.
  140.  
  141.    Returns 1 on fail.                                                         */
  142. BOOL S3M_GetNumChannels(void)
  143. {
  144.     int row=0,flag,ch;
  145.  
  146.     while(row<64) {
  147.         flag=_mm_read_UBYTE(modfp);
  148.  
  149.         if(feof(modfp)) {
  150.             _mm_errno = MMERR_LOADING_PATTERN;
  151.             return 1;
  152.         }
  153.  
  154.         if(flag) {
  155.             ch=flag&31;
  156.             if(mh->channels[ch]<32) remap[ch] = 0;
  157.             if(flag&32) {_mm_read_UBYTE(modfp);_mm_read_UBYTE(modfp);}
  158.             if(flag&64) _mm_read_UBYTE(modfp);
  159.             if(flag&128){_mm_read_UBYTE(modfp);_mm_read_UBYTE(modfp);}
  160.         } else row++;
  161.     }
  162.     return 0;
  163. }    
  164.  
  165. BOOL S3M_ReadPattern(void)
  166. {
  167.     int row=0,flag,ch;
  168.     S3MNOTE *n,dummy;
  169.  
  170.     /* clear pattern data */
  171.     memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
  172.  
  173.     while(row<64) {
  174.         flag=_mm_read_UBYTE(modfp);
  175.  
  176.         if(feof(modfp)) {
  177.             _mm_errno = MMERR_LOADING_PATTERN;
  178.             return 0;
  179.         }
  180.  
  181.         if(flag) {
  182.             ch=remap[flag&31];
  183.  
  184.             if(ch!=-1)
  185.                 n=&s3mbuf[(64U*ch)+row];
  186.             else
  187.                 n=&dummy;
  188.  
  189.             if(flag&32) {
  190.                 n->note=_mm_read_UBYTE(modfp);
  191.                 n->ins=_mm_read_UBYTE(modfp);
  192.             }
  193.             if(flag&64)
  194.                 n->vol=_mm_read_UBYTE(modfp);
  195.             if(flag&128) {
  196.                 n->cmd=_mm_read_UBYTE(modfp);
  197.                 n->inf=_mm_read_UBYTE(modfp);
  198.             }
  199.         } else row++;
  200.     }
  201.     return 1;
  202. }
  203.  
  204. UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
  205. {
  206.     int t;
  207.     UBYTE note,ins,vol;
  208.  
  209.     UniReset();
  210.     for(t=0;t<64;t++) {
  211.         note=tr[t].note;
  212.         ins=tr[t].ins;
  213.         vol=tr[t].vol;
  214.  
  215.         if((ins)&&(ins!=255)) UniInstrument(ins-1);
  216.         if(note!=255) {
  217.             if(note==254) UniPTEffect(0xc,0);    /* note cut command */
  218.             else UniNote(((note>>4)*OCTAVE)+(note&0xf));    /* normal note */
  219.         }
  220.         if(vol<255) UniPTEffect(0xc,vol);
  221.  
  222.         S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,1);
  223.         UniNewline();
  224.     }
  225.     return UniDup();
  226. }
  227.  
  228. BOOL S3M_Load(BOOL curious)
  229. {
  230.     int t,u,track = 0;
  231.     SAMPLE *q;
  232.     UBYTE pan[32];
  233.  
  234.     /* try to read module header */
  235.     _mm_read_string(mh->songname,28,modfp);
  236.     mh->t1a         =_mm_read_UBYTE(modfp);
  237.     mh->type        =_mm_read_UBYTE(modfp);
  238.     _mm_read_UBYTES(mh->unused1,2,modfp);
  239.     mh->ordnum      =_mm_read_I_UWORD(modfp);
  240.     mh->insnum      =_mm_read_I_UWORD(modfp);
  241.     mh->patnum      =_mm_read_I_UWORD(modfp);
  242.     mh->flags       =_mm_read_I_UWORD(modfp);
  243.     mh->tracker     =_mm_read_I_UWORD(modfp);
  244.     mh->fileformat  =_mm_read_I_UWORD(modfp);
  245.     _mm_read_string(mh->scrm,4,modfp);
  246.     mh->mastervol   =_mm_read_UBYTE(modfp);
  247.     mh->initspeed   =_mm_read_UBYTE(modfp);
  248.     mh->inittempo   =_mm_read_UBYTE(modfp);
  249.     mh->mastermult  =_mm_read_UBYTE(modfp);
  250.     mh->ultraclick  =_mm_read_UBYTE(modfp);
  251.     mh->pantable    =_mm_read_UBYTE(modfp);
  252.     _mm_read_UBYTES(mh->unused2,8,modfp);
  253.     mh->special     =_mm_read_I_UWORD(modfp);
  254.     _mm_read_UBYTES(mh->channels,32,modfp);
  255.  
  256.     if(feof(modfp)) {
  257.         _mm_errno = MMERR_LOADING_HEADER;
  258.         return 0;
  259.     }
  260.  
  261.     /* set module variables */
  262.     of.songname    = DupStr(mh->songname,28);
  263.     of.numpat      = mh->patnum;
  264.     of.reppos      = 0;
  265.     of.numins      = of.numsmp = mh->insnum;
  266.     of.initspeed   = mh->initspeed;
  267.     of.inittempo   = mh->inittempo;
  268.     of.initvolume  = mh->mastervol<<1;
  269.     if((mh->tracker==0x1300)||(mh->flags&64))
  270.         of.flags|=UF_S3MSLIDES;
  271.  
  272.     /* read the order data */
  273.     if(!AllocPositions(mh->ordnum)) return 0;
  274.     for(t=0;t<mh->ordnum;t++)
  275.         of.positions[t]=_mm_read_UBYTE(modfp);
  276.  
  277.     of.numpos=0;poslookupcnt=mh->ordnum;
  278.     for(t=0;t<mh->ordnum;t++) {
  279.         of.positions[of.numpos]=of.positions[t];
  280.         poslookup[t]=of.numpos;    /* bug fix for freaky S3Ms */
  281.         if(of.positions[t]<254) of.numpos++;        
  282.         else
  283.           /* special end of song pattern */
  284.           if((of.positions[t]==255)&&(!curious)) break;
  285.     }
  286.  
  287.     if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
  288.         return 0;
  289.  
  290.     /* read the instrument+pattern parapointers */
  291.     _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modfp);
  292.  
  293.     if(mh->pantable==252) {
  294.         /* read the panning table (ST 3.2 addition.  See below for further
  295.            portions of channel panning [past reampper]). */
  296.         _mm_read_UBYTES(pan,32,modfp);
  297.     }
  298.  
  299.     if(feof(modfp)) {
  300.         _mm_errno = MMERR_LOADING_HEADER;
  301.         return 0;
  302.     }
  303.  
  304.     /* load samples */
  305.     if(!AllocSamples()) return 0;
  306.     q = of.samples;
  307.     for(t=0;t<of.numins;t++) {
  308.         S3MSAMPLE s;
  309.  
  310.         /* seek to instrument position */
  311.         _mm_fseek(modfp,((long)paraptr[t])<<4,SEEK_SET);
  312.         /* and load sample info */
  313.         s.type      =_mm_read_UBYTE(modfp);
  314.         _mm_read_string(s.filename,12,modfp);
  315.         s.memsegh   =_mm_read_UBYTE(modfp);
  316.         s.memsegl   =_mm_read_I_UWORD(modfp);
  317.         s.length    =_mm_read_I_ULONG(modfp);
  318.         s.loopbeg   =_mm_read_I_ULONG(modfp);
  319.         s.loopend   =_mm_read_I_ULONG(modfp);
  320.         s.volume    =_mm_read_UBYTE(modfp);
  321.         s.dsk       =_mm_read_UBYTE(modfp);
  322.         s.pack      =_mm_read_UBYTE(modfp);
  323.         s.flags     =_mm_read_UBYTE(modfp);
  324.         s.c2spd     =_mm_read_I_ULONG(modfp);
  325.         _mm_read_UBYTES(s.unused,12,modfp);
  326.         _mm_read_string(s.sampname,28,modfp);
  327.         _mm_read_string(s.scrs,4,modfp);
  328.  
  329.         if(feof(modfp)) {
  330.             _mm_errno = MMERR_LOADING_SAMPLEINFO;
  331.             return 0;
  332.         }
  333.  
  334.         q->samplename = DupStr(s.sampname,28);
  335.         q->speed      = s.c2spd;
  336.         q->length     = s.length;
  337.         q->loopstart  = s.loopbeg;
  338.         q->loopend    = s.loopend;
  339.         q->volume     = s.volume;
  340.         q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  341.  
  342.         if(s.flags&1) q->flags |= SF_LOOP;
  343.         if(s.flags&4) q->flags |= SF_16BITS;
  344.         if(mh->fileformat==1) q->flags |= SF_SIGNED;
  345.  
  346.         /* don't load sample if it doesn't have the SCRS tag */
  347.         if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
  348.  
  349.         q++;
  350.     }
  351.  
  352.     /* determine the number of channels actually used. */
  353.     of.numchn = 0;
  354.     memset(remap,-1,32*sizeof(UBYTE));
  355.     for(t=0;t<of.numpat;t++) {
  356.         /* seek to pattern position (+2 skip pattern length) */
  357.         _mm_fseek(modfp,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  358.         if(S3M_GetNumChannels()) return 0;
  359.     }
  360.  
  361.     /* then we can decide the module type */
  362.     if((((mh->tracker>>8)&0xf)==1)||(of.numchn>16))
  363.         of.modtype = strdup(S3M_Version[1]); /* Imago orpheus */
  364.     else
  365.         of.modtype = strdup(S3M_Version[0]); /* Scream tracker */
  366.     /* We're lucky, both names have the same length... */
  367.     of.modtype[14] = ((mh->tracker>>8) &0xf)+'0';
  368.     of.modtype[16] = ((mh->tracker>>4)&0xf)+'0';
  369.     of.modtype[17] = ((mh->tracker)&0xf)+'0';
  370.  
  371.     /* build the remap array  */
  372.     for(t=0;t<32;t++)
  373.         if(!remap[t]) 
  374.             remap[t]=of.numchn++;
  375.  
  376.     /* set panning positions after building remap chart! */
  377.     for(t=0;t<32;t++) 
  378.         if((mh->channels[t]<32)&&(remap[t]!=-1)) {
  379.             if(mh->channels[t]<8)
  380.                 of.panning[remap[t]]=0x20;    /* 0x30 = std s3m val */
  381.             else
  382.                 of.panning[remap[t]]=0xd0;    /* 0xc0 = std s3m val */
  383.         }
  384.     if(mh->pantable==252)
  385.         /* set panning positions according to panning table (new for st3.2) */
  386.         for(t=0;t<32;t++)
  387.             if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
  388.                 of.panning[remap[t]]=(pan[t]&0xf)<<4;
  389.  
  390.     /* load pattern info */
  391.     of.numtrk=of.numpat*of.numchn;
  392.     if(!AllocTracks()) return 0;
  393.     if(!AllocPatterns()) return 0;
  394.  
  395.     for(t=0;t<of.numpat;t++) {
  396.         /* seek to pattern position (+2 skip pattern length) */
  397.         _mm_fseek(modfp,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  398.         if(!S3M_ReadPattern()) return 0;
  399.         for(u=0;u<of.numchn;u++)
  400.             if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  401.     }
  402.  
  403.     return 1;
  404. }
  405.  
  406. CHAR *S3M_LoadTitle(void)
  407. {
  408.     CHAR s[28];
  409.  
  410.     _mm_fseek(modfp,0,SEEK_SET);
  411.     if(!fread(s,28,1,modfp)) return NULL;
  412.  
  413.     return(DupStr(s,28));
  414. }
  415.  
  416. /*========== Loader information */
  417.  
  418. MLOADER load_s3m={
  419.     NULL,
  420.     "S3M",
  421.     "S3M loader v1.0",
  422.     S3M_Init,
  423.     S3M_Test,
  424.     S3M_Load,
  425.     S3M_Cleanup,
  426.     S3M_LoadTitle
  427. };
  428.