home *** CD-ROM | disk | FTP | other *** search
- /* MikMod sound library
- (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*==============================================================================
-
- $Id: load_mtm.c,v 1.17 1998/12/07 06:00:19 miod Exp $
-
- MTM module loader
-
- ==============================================================================*/
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #include <string.h>
-
- #include <mikmod_internals.h>
-
- /*========== Module structure */
-
- typedef struct MTMHEADER {
- UBYTE id[3]; /* MTM file marker */
- UBYTE version; /* upper major, lower nibble minor version number */
- CHAR songname[20]; /* ASCIIZ songname */
- UWORD numtracks; /* number of tracks saved */
- UBYTE lastpattern; /* last pattern number saved */
- UBYTE lastorder; /* last order number to play (songlength-1) */
- UWORD commentsize; /* length of comment field */
- UBYTE numsamples; /* number of samples saved */
- UBYTE attribute; /* attribute byte (unused) */
- UBYTE beatspertrack;
- UBYTE numchannels; /* number of channels used */
- UBYTE panpos[32]; /* voice pan positions */
- } MTMHEADER;
-
- typedef struct MTMSAMPLE {
- CHAR samplename[22];
- ULONG length;
- ULONG reppos;
- ULONG repend;
- UBYTE finetune;
- UBYTE volume;
- UBYTE attribute;
- } MTMSAMPLE;
-
- typedef struct MTMNOTE {
- UBYTE a,b,c;
- } MTMNOTE;
-
- /*========== Loader variables */
-
- static MTMHEADER *mh = NULL;
- static MTMNOTE *mtmtrk = NULL;
- static UWORD pat[32];
-
- CHAR MTM_Version[] = "MTM";
-
- /*========== Loader code */
-
- BOOL MTM_Test(void)
- {
- UBYTE id[3];
-
- if(!_mm_read_UBYTES(id,3,modfp)) return 0;
- if(!memcmp(id,"MTM",3)) return 1;
- return 0;
- }
-
- BOOL MTM_Init(void)
- {
- if(!(mtmtrk=(MTMNOTE*)_mm_calloc(64,sizeof(MTMNOTE)))) return 0;
- if(!(mh=(MTMHEADER*)_mm_malloc(sizeof(MTMHEADER)))) return 0;
-
- return 1;
- }
-
- void MTM_Cleanup(void)
- {
- if(mtmtrk) free(mtmtrk);
- if(mh) free(mh);
-
- mtmtrk = NULL;
- mh = NULL;
- }
-
- UBYTE* MTM_Convert(void)
- {
- int t;
- UBYTE a,b,inst,note,eff,dat;
-
- UniReset();
- for(t=0;t<64;t++) {
- a=mtmtrk[t].a;
- b=mtmtrk[t].b;
- inst=((a&0x3)<<4)|(b>>4);
- note=a>>2;
- eff=b&0xf;
- dat=mtmtrk[t].c;
-
- if(inst) UniInstrument(inst-1);
- if(note) UniNote(note+2*OCTAVE);
-
- /* MTM bug workaround : when the effect is volslide, slide-up *always*
- overrides slide-down. */
- if(eff==0xa && (dat&0xf0)) dat&=0xf0;
-
- /* Convert pattern jump from Dec to Hex */
- if(eff==0xd)
- dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
- /* finetune conversion to Lxx */
- if(eff==5)
- S3MIT_ProcessCmd(0xc,dat,1);
- else
- UniPTEffect(eff,dat);
- UniNewline();
- }
- return UniDup();
- }
-
- BOOL MTM_Load(BOOL curious)
- {
- int t,u;
- MTMSAMPLE s;
- SAMPLE *q;
-
- /* try to read module header */
- _mm_read_UBYTES(mh->id,3,modfp);
- mh->version =_mm_read_UBYTE(modfp);
- _mm_read_string(mh->songname,20,modfp);
- mh->numtracks =_mm_read_I_UWORD(modfp);
- mh->lastpattern =_mm_read_UBYTE(modfp);
- mh->lastorder =_mm_read_UBYTE(modfp);
- mh->commentsize =_mm_read_I_UWORD(modfp);
- mh->numsamples =_mm_read_UBYTE(modfp);
- mh->attribute =_mm_read_UBYTE(modfp);
- mh->beatspertrack=_mm_read_UBYTE(modfp);
- mh->numchannels =_mm_read_UBYTE(modfp);
- _mm_read_UBYTES(mh->panpos,32,modfp);
-
- if(feof(modfp)) {
- _mm_errno = MMERR_LOADING_HEADER;
- return 0;
- }
-
- /* set module variables */
- of.initspeed = 6;
- of.inittempo = 125;
- of.modtype = strdup(MTM_Version);
- of.numchn = mh->numchannels;
- of.numtrk = mh->numtracks+1; /* get number of channels */
- of.songname = DupStr(mh->songname,20); /* make a cstr of songname */
- of.numpos = mh->lastorder+1; /* copy the songlength */
- of.numpat = mh->lastpattern+1;
- of.reppos = 0;
- for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<< 4;
- of.numins=of.numsmp=mh->numsamples;
-
- if(!AllocSamples()) return 0;
- q=of.samples;
- for(t=0;t<of.numins;t++) {
- /* try to read sample info */
- _mm_read_string(s.samplename,22,modfp);
- s.length =_mm_read_I_ULONG(modfp);
- s.reppos =_mm_read_I_ULONG(modfp);
- s.repend =_mm_read_I_ULONG(modfp);
- s.finetune =_mm_read_UBYTE(modfp);
- s.volume =_mm_read_UBYTE(modfp);
- s.attribute =_mm_read_UBYTE(modfp);
-
- if(feof(modfp)) {
- _mm_errno = MMERR_LOADING_SAMPLEINFO;
- return 0;
- }
-
- q->samplename = DupStr(s.samplename,22);
- q->seekpos = 0;
- q->speed = finetune[s.finetune];
- q->length = s.length;
- q->loopstart = s.reppos;
- q->loopend = s.repend;
- q->volume = s.volume;
- if((s.repend-s.reppos)>2) q->flags |= SF_LOOP;
-
- if(s.attribute&1) {
- /* If the sample is 16-bits, convert the length and replen
- byte-values into sample-values */
- q->flags|=SF_16BITS;
- q->length>>=1;
- q->loopstart>>=1;
- q->loopend>>=1;
- }
-
- q++;
- }
-
- if(!AllocPositions(of.numpos)) return 0;
- for(t=0;t<of.numpos;t++)
- of.positions[t]=_mm_read_UBYTE(modfp);
- for(;t<128;t++) _mm_read_UBYTE(modfp);
- if(feof(modfp)) {
- _mm_errno = MMERR_LOADING_HEADER;
- return 0;
- }
-
- if(!AllocTracks()) return 0;
- if(!AllocPatterns()) return 0;
-
- of.tracks[0]=MTM_Convert(); /* track 0 is empty */
- for(t=1;t<of.numtrk;t++) {
- int s;
-
- for(s=0;s<64;s++) {
- mtmtrk[s].a=_mm_read_UBYTE(modfp);
- mtmtrk[s].b=_mm_read_UBYTE(modfp);
- mtmtrk[s].c=_mm_read_UBYTE(modfp);
- }
-
- if(feof(modfp)) {
- _mm_errno = MMERR_LOADING_TRACK;
- return 0;
- }
-
- if(!(of.tracks[t]=MTM_Convert())) return 0;
- }
-
- for(t=0;t<of.numpat;t++) {
- _mm_read_I_UWORDS(pat,32,modfp);
- for(u=0;u<of.numchn;u++)
- of.patterns[((long)t*of.numchn)+u]=pat[u];
- }
-
- /* read comment field */
- if(mh->commentsize)
- if(!ReadLinedComment(mh->commentsize/40,40)) return 0;
-
- return 1;
- }
-
- CHAR *MTM_LoadTitle(void)
- {
- CHAR s[20];
-
- _mm_fseek(modfp,4,SEEK_SET);
- if(!fread(s,20,1,modfp)) return NULL;
-
- return(DupStr(s,20));
- }
-
- /*========== Loader information */
-
- MLOADER load_mtm={
- NULL,
- "MTM",
- "MTM loader v1.0",
- MTM_Init,
- MTM_Test,
- MTM_Load,
- MTM_Cleanup,
- MTM_LoadTitle
- };
-