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_stm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  8.8 KB  |  353 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_stm.c,v 1.18 1998/12/07 06:00:21 miod Exp $
  22.  
  23.   Screamtracker 2 (STM) 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. /* sample information */
  38. typedef struct STMSAMPLE {
  39.     CHAR  filename[12];
  40.     UBYTE unused;       /* 0x00 */
  41.     UBYTE instdisk;     /* Instrument disk */
  42.     UWORD reserved;
  43.     UWORD length;       /* Sample length */
  44.     UWORD loopbeg;      /* Loop start point */
  45.     UWORD loopend;      /* Loop end point */
  46.     UBYTE volume;       /* Volume */
  47.     UBYTE reserved2;
  48.     UWORD c2spd;        /* Good old c2spd */
  49.     ULONG reserved3;
  50.     UWORD isa;
  51. } STMSAMPLE;
  52.  
  53. /* header */
  54. typedef struct STMHEADER {
  55.     CHAR  songname[20];
  56.     CHAR  trackername[8]; /* !SCREAM! for ST 2.xx  */
  57.     UBYTE unused;         /* 0x1A  */
  58.     UBYTE filetype;       /* 1=song, 2=module */
  59.     UBYTE ver_major;
  60.     UBYTE ver_minor;
  61.     UBYTE inittempo;      /* initspeed= stm inittempo>>4  */
  62.     UBYTE numpat;         /* number of patterns  */
  63.     UBYTE globalvol;     
  64.     UBYTE reserved[13];
  65.     STMSAMPLE sample[31]; /* STM sample data */
  66.     UBYTE patorder[128];  /* Docs say 64 - actually 128 */
  67. } STMHEADER;
  68.  
  69. typedef struct STMNOTE {
  70.     UBYTE note,insvol,volcmd,cmdinf;
  71. } STMNOTE;
  72.  
  73. /*========== Loader variables */
  74.  
  75. static STMNOTE *stmbuf = NULL;
  76. static STMHEADER *mh = NULL;
  77.  
  78. static CHAR  STM_Version[] = "Screamtracker 2";
  79.  
  80. /*========== Loader code */
  81.  
  82. BOOL STM_Test(void)
  83. {
  84.     UBYTE str[9],filetype;
  85.  
  86.     _mm_fseek(modfp,20,SEEK_SET);
  87.     _mm_read_UBYTES(str,9,modfp);
  88.     filetype=_mm_read_UBYTE(modfp);
  89.     if((memcmp(str,"!Scream!",8))||(filetype!=2)) /* STM Module = filetype 2 */
  90.         return 0;
  91.     return 1;
  92. }
  93.  
  94. BOOL STM_Init(void)
  95. {
  96.     if(!(mh=(STMHEADER*)_mm_malloc(sizeof(STMHEADER)))) return 0;
  97.     if(!(stmbuf=(STMNOTE*)_mm_calloc(64U*4,sizeof(STMNOTE)))) return 0;
  98.  
  99.     return 1;
  100. }
  101.  
  102. void STM_Cleanup(void)
  103. {
  104.     if(mh) free(mh);
  105.     if(stmbuf) free(stmbuf);
  106.  
  107.     stmbuf = NULL;
  108.     mh = NULL;
  109. }
  110.  
  111. void STM_ConvertNote(STMNOTE *n)
  112. {
  113.     UBYTE note,ins,vol,cmd,inf;
  114.  
  115.     /* extract the various information from the 4 bytes that make up a note */
  116.     note = n->note;
  117.     ins  = n->insvol>>3;
  118.     vol  = (n->insvol&7)+(n->volcmd>>1);
  119.     cmd  = n->volcmd&15;
  120.     inf  = n->cmdinf;
  121.  
  122.     if((ins)&&(ins<32)) UniInstrument(ins-1);
  123.  
  124.     /* special values of [SBYTE0] are handled here 
  125.        we have no idea if these strange values will ever be encountered.
  126.        but it appears as though stms sound correct. */
  127.     if((note==254)||(note==252)) UniPTEffect(0xc,0); /* note cut */
  128.     else
  129.         /* if note < 251, then all three bytes are stored in the file */
  130.       if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf));
  131.  
  132.     if(vol<65) UniPTEffect(0xc,vol);
  133.     if(cmd!=255)
  134.         switch(cmd) {
  135.             case 1:    /* Axx set speed to xx and add 0x1c to fix STM 2.x bug */
  136.                 UniPTEffect(0xf,inf>>4);
  137.                 break;
  138.             case 2:    /* Bxx position jump */
  139.                 UniPTEffect(0xb,inf);
  140.                 break;
  141.             case 3:    /* Cxx patternbreak to row xx */
  142.                 UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
  143.                 break;
  144.             case 4:    /* Dxy volumeslide */
  145.                 UniWrite(UNI_S3MEFFECTD);
  146.                 UniWrite(inf);
  147.                 break;
  148.             case 5:    /* Exy toneslide down */
  149.                 UniWrite(UNI_S3MEFFECTE);
  150.                 UniWrite(inf);
  151.                 break;
  152.             case 6:    /* Fxy toneslide up */
  153.                 UniWrite(UNI_S3MEFFECTF);
  154.                 UniWrite(inf);
  155.                 break;
  156.             case 7:    /* Gxx Tone portamento,speed xx */
  157.                 UniPTEffect(0x3,inf);
  158.                 break;
  159.             case 8:    /* Hxy vibrato */
  160.                 UniPTEffect(0x4,inf);
  161.                 break;
  162.             case 9:    /* Ixy tremor, ontime x, offtime y */
  163.                 UniWrite(UNI_S3MEFFECTI);
  164.                 UniWrite(inf);
  165.             break;
  166.             case 0xa:    /* Jxy arpeggio */
  167.                 UniPTEffect(0x0,inf);
  168.                 break;
  169.             case 0xb:    /* Kxy Dual command H00 & Dxy */
  170.                 UniPTEffect(0x4,0);
  171.                 UniWrite(UNI_S3MEFFECTD);
  172.                 UniWrite(inf);
  173.                 break;
  174.             case 0xc:    /* Lxy Dual command G00 & Dxy */
  175.                 UniPTEffect(0x3,0);
  176.                 UniWrite(UNI_S3MEFFECTD);
  177.                 UniWrite(inf);
  178.                 break;
  179.  
  180.             /* Support all these above, since ST2 can LOAD these values but can
  181.                actually only play up to J - and J is only half-way implemented
  182.                in ST2 */
  183.             case 0x18:    /* Xxx amiga panning command 8xx */
  184.                 UniPTEffect(0x8,inf);
  185.                 break;
  186.         }
  187. }
  188.  
  189. UBYTE *STM_ConvertTrack(STMNOTE *n)
  190. {
  191.     int t;
  192.  
  193.     UniReset();
  194.     for(t=0;t<64;t++) {
  195.         STM_ConvertNote(n);
  196.         UniNewline();
  197.         n+=of.numchn;
  198.     }
  199.     return UniDup();
  200. }
  201.  
  202. BOOL STM_LoadPatterns(void)
  203. {
  204.     int t,s,tracks=0;
  205.  
  206.     if(!AllocPatterns()) return 0;
  207.     if(!AllocTracks()) return 0;
  208.  
  209.     /* Allocate temporary buffer for loading and converting the patterns */
  210.     for(t=0;t<of.numpat;t++) {
  211.         for(s=0;s<(64U*of.numchn);s++) {
  212.             stmbuf[s].note   = _mm_read_UBYTE(modfp);
  213.             stmbuf[s].insvol = _mm_read_UBYTE(modfp);
  214.             stmbuf[s].volcmd = _mm_read_UBYTE(modfp);
  215.             stmbuf[s].cmdinf = _mm_read_UBYTE(modfp);
  216.         }
  217.  
  218.         if(feof(modfp)) {
  219.             _mm_errno = MMERR_LOADING_PATTERN;
  220.             return 0;
  221.         }
  222.  
  223.         for(s=0;s<of.numchn;s++)
  224.             if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
  225.     }
  226.     return 1;
  227. }
  228.  
  229. BOOL STM_Load(BOOL curious)
  230. {
  231.     int t; 
  232.     ULONG MikMod_ISA; /* We must generate our own ISA, it's not stored in stm */
  233.     SAMPLE *q;
  234.  
  235.     /* try to read stm header */
  236.     _mm_read_string(mh->songname,20,modfp);
  237.     _mm_read_string(mh->trackername,8,modfp);
  238.     mh->unused      =_mm_read_UBYTE(modfp);
  239.     mh->filetype    =_mm_read_UBYTE(modfp);
  240.     mh->ver_major   =_mm_read_UBYTE(modfp);
  241.     mh->ver_minor   =_mm_read_UBYTE(modfp);
  242.     mh->inittempo   =_mm_read_UBYTE(modfp);
  243.     if(!mh->inittempo) {
  244.         _mm_errno=MMERR_NOT_A_MODULE;
  245.         return 0;
  246.     }
  247.     mh->numpat      =_mm_read_UBYTE(modfp);
  248.     mh->globalvol   =_mm_read_UBYTE(modfp);
  249.     _mm_read_UBYTES(mh->reserved,13,modfp);
  250.  
  251.     for(t=0;t<31;t++) {
  252.         STMSAMPLE *s=&mh->sample[t];    /* STM sample data */
  253.  
  254.         _mm_read_string(s->filename,12,modfp);
  255.         s->unused   =_mm_read_UBYTE(modfp);
  256.         s->instdisk =_mm_read_UBYTE(modfp);
  257.         s->reserved =_mm_read_I_UWORD(modfp);
  258.         s->length   =_mm_read_I_UWORD(modfp);
  259.         s->loopbeg  =_mm_read_I_UWORD(modfp);
  260.         s->loopend  =_mm_read_I_UWORD(modfp);
  261.         s->volume   =_mm_read_UBYTE(modfp);
  262.         s->reserved2=_mm_read_UBYTE(modfp);
  263.         s->c2spd    =_mm_read_I_UWORD(modfp);
  264.         s->reserved3=_mm_read_I_ULONG(modfp);
  265.         s->isa      =_mm_read_I_UWORD(modfp);
  266.     }
  267.     _mm_read_UBYTES(mh->patorder,128,modfp);
  268.  
  269.     if(feof(modfp)) {
  270.         _mm_errno = MMERR_LOADING_HEADER;
  271.         return 0;
  272.     }
  273.  
  274.     /* set module variables */
  275.     of.modtype   = strdup(STM_Version);
  276.     of.songname  = DupStr(mh->songname,20); /* make a cstr of songname */
  277.     of.numpat    = mh->numpat;
  278.     of.inittempo = 125;                     /* mh->inittempo+0x1c; */
  279.     of.initspeed = mh->inittempo>>4;
  280.     of.numchn    = 4;                       /* get number of channels */
  281.     of.reppos    = 0;
  282.     of.flags    |= UF_S3MSLIDES;
  283.  
  284.     t=0;
  285.     if(!AllocPositions(0x80)) return 0;
  286.     while(mh->patorder[t]!=99) {    /* 99 terminates the patorder list */
  287.         of.positions[t]=mh->patorder[t];
  288.         t++;
  289.     }
  290.     of.numpos=--t;
  291.     of.numtrk=of.numpat*of.numchn;
  292.     of.numins=of.numsmp=31;
  293.  
  294.     if(!AllocSamples()) return 0;
  295.     if(!STM_LoadPatterns()) return 0;
  296.     q = of.samples;
  297.     MikMod_ISA=_mm_ftell(modfp);
  298.     MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;    /* normalize */
  299.  
  300.     for(t=0;t<of.numsmp;t++) {
  301.         /* load sample info */
  302.         q->samplename = DupStr(mh->sample[t].filename,12);
  303.         q->speed      = mh->sample[t].c2spd;
  304.         q->volume     = mh->sample[t].volume;
  305.         q->length     = mh->sample[t].length;
  306.         if ((!mh->sample[t].volume)||(q->length==1)) q->length=0;
  307.         q->loopstart  = mh->sample[t].loopbeg;
  308.         q->loopend    = mh->sample[t].loopend;
  309.         q->seekpos    = MikMod_ISA;
  310.  
  311.         MikMod_ISA+=q->length;
  312.         MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;    /* normalize */
  313.  
  314.         /* contrary to the STM specs, sample data is signed */
  315.         q->flags = SF_SIGNED;
  316.  
  317.         /* fix for bad STMs */
  318.         if (q->loopstart>=q->length) q->loopstart=q->loopend=0;
  319.  
  320.         if((mh->sample[t].loopend>0)&&(mh->sample[t].loopend!=0xffff))
  321.             q->flags|=SF_LOOP;
  322.         /* fix replen if repend>length */
  323.         if(q->loopend>q->length) q->loopend = q->length;
  324.  
  325.         q++;
  326.     }
  327.     return 1;
  328. }
  329.  
  330. CHAR *STM_LoadTitle(void)
  331. {
  332.     CHAR s[20];
  333.  
  334.     _mm_fseek(modfp,0,SEEK_SET);
  335.     if(!fread(s,20,1,modfp)) return NULL;
  336.  
  337.     return(DupStr(s,20));
  338. }
  339.  
  340. /*========== Loader information */
  341.  
  342. MLOADER load_stm={
  343.     NULL,
  344.     "STM",
  345.     "STM Loader v1.3",
  346.     STM_Init,
  347.     STM_Test,
  348.     STM_Load,
  349.     STM_Cleanup,
  350.     STM_LoadTitle
  351. };
  352.  
  353.