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_mod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  8.9 KB  |  347 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_mod.c,v 1.17 1998/12/07 06:00:17 miod Exp $
  22.  
  23.   Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
  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 MSAMPINFO {
  38.     CHAR  samplename[23];    /* 22 in module, 23 in memory */
  39.     UWORD length;
  40.     UBYTE finetune;
  41.     UBYTE volume;
  42.     UWORD reppos;
  43.     UWORD replen;
  44. } MSAMPINFO;
  45.  
  46. typedef struct MODULEHEADER {
  47.     CHAR      songname[21];        /* the songname.. 20 in module, 21 in memory */
  48.     MSAMPINFO samples[31];        /* all sampleinfo */
  49.     UBYTE     songlength;        /* number of patterns used */
  50.     UBYTE     magic1;            /* should be 127 */
  51.     UBYTE     positions[128];    /* which pattern to play at pos */
  52.     UBYTE     magic2[4];        /* string "M.K." or "FLT4" or "FLT8" */
  53. } MODULEHEADER;
  54.  
  55. typedef struct MODTYPE {
  56.     CHAR  id[5];
  57.     UBYTE channels;
  58.     CHAR  *name;
  59. } MODTYPE;
  60.  
  61. typedef struct MODNOTE {
  62.     UBYTE a,b,c,d;
  63. } MODNOTE;
  64.  
  65. /*========== Loader variables */
  66.  
  67. #define MODULEHEADERSIZE 1084
  68.  
  69. CHAR protracker[]   = "Protracker";
  70. CHAR startracker[]  = "Startracker";
  71. CHAR fasttracker[]  = "Fasttracker";
  72. CHAR ins15tracker[] = "15-instrument";
  73. CHAR oktalyzer[]    = "Oktalyzer";
  74. CHAR taketracker[]  = "TakeTracker";
  75.  
  76. #define MODTYPE_COUNT 24
  77. MODTYPE modtypes[MODTYPE_COUNT+1]={
  78.     {"M.K.", 4,  protracker},    /* protracker 4 channel */
  79.     {"M!K!", 4,  protracker},    /* protracker 4 channel */
  80.     {"FLT4", 4, startracker},    /* startracker 4 channel */
  81.     {"2CHN", 2, fasttracker},    /* fasttracker 2 channel */
  82.     {"4CHN", 4, fasttracker},    /* fasttracker 4 channel */
  83.     {"6CHN", 6, fasttracker},    /* fasttracker 6 channel */
  84.     {"8CHN", 8, fasttracker},    /* fasttracker 8 channel */
  85.     {"10CH",10, fasttracker},    /* fasttracker 10 channel */
  86.     {"12CH",12, fasttracker},    /* fasttracker 12 channel */
  87.     {"14CH",14, fasttracker},    /* fasttracker 14 channel */
  88.     {"15CH",15, fasttracker},    /* fasttracker 15 channel */
  89.     {"16CH",16, fasttracker},    /* fasttracker 16 channel */
  90.     {"18CH",18, fasttracker},    /* fasttracker 18 channel */
  91.     {"20CH",20, fasttracker},    /* fasttracker 20 channel */
  92.     {"22CH",22, fasttracker},    /* fasttracker 22 channel */
  93.     {"24CH",24, fasttracker},    /* fasttracker 24 channel */
  94.     {"26CH",26, fasttracker},    /* fasttracker 26 channel */
  95.     {"28CH",28, fasttracker},    /* fasttracker 28 channel */
  96.     {"30CH",30, fasttracker},    /* fasttracker 30 channel */
  97.     {"32CH",32, fasttracker},    /* fasttracker 32 channel */
  98.     {"CD81", 8,   oktalyzer},    /* atari oktalyzer 8 channel */
  99.     {"OKTA", 8,   oktalyzer},    /* atari oktalyzer 8 channel */
  100.     {"16CN",16, taketracker},    /* taketracker 16 channel */
  101.     {"32CN",32, taketracker},    /* taketracker 32 channel */
  102.     {"    ", 4,ins15tracker}    /* 15-instrument 4 channel */
  103. };
  104.  
  105. static MODULEHEADER *mh = NULL;
  106. static MODNOTE *patbuf = NULL;
  107. static int modtype = 0;
  108.  
  109. /*========== Loader code */
  110.  
  111. BOOL MOD_Test(void)
  112. {
  113.     UBYTE id[4];
  114.  
  115.     _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
  116.     if(!fread(id,4,1,modfp)) return 0;
  117.  
  118.     /* find out which ID string */
  119.     for(modtype=0;modtype<MODTYPE_COUNT;modtype++)
  120.         if(!memcmp(id,modtypes[modtype].id,4)) return 1;
  121.  
  122.     return 0;
  123. }
  124.  
  125. BOOL MOD_Init(void)
  126. {
  127.     if(    !(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
  128.     return 1;
  129. }
  130.  
  131. void MOD_Cleanup(void)
  132. {
  133.     if(mh) free(mh);
  134.     if(patbuf) free(patbuf);
  135.  
  136.     mh = NULL;
  137.     patbuf = NULL;
  138. }
  139.  
  140. /*
  141. Old (amiga) noteinfo:
  142.  
  143. _____byte 1_____   byte2_    _____byte 3_____   byte4_
  144. /                \ /      \  /                \ /      \
  145. 0000          0000-00000000  0000          0000-00000000
  146.  
  147. Upper four    12 bits for    Lower four    Effect command.
  148. bits of sam-  note period.   bits of sam-
  149. ple number.                  ple number.
  150.  
  151. */
  152.  
  153. void ConvertNote(MODNOTE* n)
  154. {
  155.     UBYTE instrument,effect,effdat,note;
  156.     UWORD period;
  157.     UBYTE lastnote=0;
  158.  
  159.     /* extract the various information from the 4 bytes that make up a note */
  160.     instrument = (n->a&0x10)|(n->c>>4);
  161.     period     = (((UWORD)n->a&0xf)<<8)+n->b;
  162.     effect     = n->c&0xf;
  163.     effdat     = n->d;
  164.  
  165.     /* Convert the period to a note number */
  166.     note=0;
  167.     if(period) {
  168.         for(note=0;note<7*OCTAVE;note++)
  169.             if(period>=npertab[note]) break;
  170.         note++;
  171.         if(note==7*OCTAVE+1) note=0;
  172.     }
  173.  
  174.     if(instrument) {
  175.         UniInstrument(instrument-1);
  176.         if(!note) note=lastnote;
  177.     }
  178.     if(note) {
  179.         UniNote(note+2*OCTAVE-1);
  180.         lastnote=note;
  181.     }
  182.  
  183.     /* Convert pattern jump from Dec to Hex */
  184.     if(effect==0xd)
  185.         effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
  186.  
  187.     /* finetune conversion to Lxx */
  188.     if(effect==5)
  189.         S3MIT_ProcessCmd(0xc,effdat,1);
  190.     else
  191.         UniPTEffect(effect,effdat);
  192. }
  193.  
  194. UBYTE* ConvertTrack(MODNOTE* n)
  195. {
  196.     int t;
  197.  
  198.     UniReset();
  199.     for(t=0;t<64;t++) {
  200.         ConvertNote(n);
  201.         UniNewline();
  202.         n+=of.numchn;
  203.     }
  204.     return UniDup();
  205. }
  206.  
  207. /* Loads all patterns of a modfile and converts them into the 3 byte format. */
  208. BOOL ML_LoadPatterns(void)
  209. {
  210.     int t,s,tracks = 0;
  211.  
  212.     if(!AllocPatterns()) return 0;
  213.     if(!AllocTracks())   return 0;
  214.  
  215.     /* Allocate temporary buffer for loading and converting the patterns */
  216.     if(!(patbuf=(MODNOTE*)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  217.  
  218.     for(t=0;t<of.numpat;t++) {
  219.         /* Load the pattern into the temp buffer and convert it */
  220.         for(s=0;s<(64U*of.numchn);s++) {
  221.             patbuf[s].a=_mm_read_UBYTE(modfp);
  222.             patbuf[s].b=_mm_read_UBYTE(modfp);
  223.             patbuf[s].c=_mm_read_UBYTE(modfp);
  224.             patbuf[s].d=_mm_read_UBYTE(modfp);
  225.         }
  226.         for(s=0;s<of.numchn;s++)
  227.             if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  228.     }
  229.     return 1;
  230. }
  231.  
  232. BOOL MOD_Load(BOOL curious)
  233. {
  234.     int t,scan;
  235.     SAMPLE *q;
  236.     MSAMPINFO *s;
  237.  
  238.     /* try to read module header */
  239.     _mm_read_string((CHAR*)mh->songname,20,modfp);
  240.     mh->songname[20]=0;    /* just in case */
  241.  
  242.     for(t=0;t<31;t++) {
  243.         s=&mh->samples[t];
  244.         _mm_read_string(s->samplename,22,modfp);
  245.         s->samplename[22]=0;    /* just in case */
  246.         s->length   =_mm_read_M_UWORD(modfp);
  247.         s->finetune =_mm_read_UBYTE(modfp);
  248.         s->volume   =_mm_read_UBYTE(modfp);
  249.         s->reppos   =_mm_read_M_UWORD(modfp);
  250.         s->replen   =_mm_read_M_UWORD(modfp);
  251.     }
  252.  
  253.     mh->songlength  =_mm_read_UBYTE(modfp);
  254.     mh->magic1      =_mm_read_UBYTE(modfp);
  255.     _mm_read_UBYTES(mh->positions,128,modfp);
  256.     _mm_read_UBYTES(mh->magic2,4,modfp);
  257.  
  258.     if(feof(modfp)) {
  259.         _mm_errno = MMERR_LOADING_HEADER;
  260.         return 0;
  261.     }
  262.  
  263.     /* set module variables */
  264.     of.initspeed = 6;
  265.     of.inittempo = 125;
  266.     of.numchn    = modtypes[modtype].channels;
  267.     of.modtype   = strdup(modtypes[modtype].name);
  268.     of.songname  = DupStr(mh->songname,21);
  269.     of.numpos    = mh->songlength;
  270.     of.reppos    = 0;
  271.  
  272.     /* Count the number of patterns */
  273.     of.numpat = 0;
  274.     for(t=0;t<of.numpos;t++)
  275.         if(mh->positions[t]>of.numpat)
  276.             of.numpat=mh->positions[t];
  277.     /* since some old modules embed extra patterns, we have to check the
  278.        whole list to get the samples' file offsets right - however we can find
  279.        garbage here, so check carefully */
  280.     scan=1;
  281.     for(t=of.numpos;t<128;t++)
  282.         if(mh->positions[t]>=0x80) scan=0;
  283.     if (scan)
  284.         for(t=of.numpos;t<128;t++) {
  285.             if(mh->positions[t]>of.numpat)
  286.                 of.numpat=mh->positions[t];
  287.             if((curious)&&(mh->positions[t])) of.numpos=t+1;
  288.         }
  289.     of.numpat++;
  290.     of.numtrk = of.numpat*of.numchn;
  291.  
  292.     if(!AllocPositions(of.numpos)) return 0;
  293.     for(t=0;t<of.numpos;t++)
  294.         of.positions[t]=mh->positions[t];
  295.  
  296.     /* Finally, init the sampleinfo structures  */
  297.     of.numins=of.numsmp=31;
  298.     if(!AllocSamples())     return 0;
  299.     s = mh->samples;
  300.     q = of.samples;
  301.     for(t=0;t<of.numins;t++) {
  302.         /* convert the samplename */
  303.         q->samplename = DupStr(s->samplename, 23);
  304.         /* init the sampleinfo variables and convert the size pointers */
  305.         q->speed     = finetune[s->finetune & 0xf];
  306.         q->volume    = s->volume;
  307.         q->loopstart = (ULONG)s->reppos << 1;
  308.         q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
  309.         q->length    = (ULONG)s->length << 1;
  310.         q->flags     = SF_SIGNED;
  311.  
  312.         if(s->replen>1) q->flags |= SF_LOOP;
  313.         /* fix replen if repend > length */
  314.         if(q->loopend>q->length) q->loopend=q->length;
  315.  
  316.         s++;
  317.         q++;
  318.     }
  319.  
  320.     if(!ML_LoadPatterns()) return 0;
  321.     return 1;
  322. }
  323.  
  324. CHAR *MOD_LoadTitle(void)
  325. {
  326.     CHAR s[21];
  327.  
  328.     _mm_fseek(modfp,0,SEEK_SET);
  329.     if(!fread(s,20,1,modfp)) return NULL;
  330.     s[20]=0;    /* just in case */
  331.  
  332.     return(DupStr(s,21));
  333. }
  334.  
  335. /*========== Loader information */
  336.  
  337. MLOADER load_mod={
  338.     NULL,
  339.     "Standard module",
  340.     "MOD loader v1.0",
  341.     MOD_Init,
  342.     MOD_Test,
  343.     MOD_Load,
  344.     MOD_Cleanup,
  345.     MOD_LoadTitle
  346. };
  347.