#include #include #include #include #include "mloader.h" #include "munitrk.h" /************************************************************************** **************************************************************************/ typedef struct MTMSAMPLE{ char samplename[22]; ULONG length; ULONG reppos; ULONG repend; UBYTE finetune; UBYTE volume; UBYTE attribute; } MTMSAMPLE; 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 MTMNOTE{ UBYTE a,b,c; } MTMNOTE; /************************************************************************** **************************************************************************/ static MTMHEADER *mh; MTMNOTE *mtmtrk; UWORD pat[32]; char MTM_Version[]="MTM"; BOOL MTM_Test(void) { char id[3]; rewind(modfp); if(!fread(id,3,1,modfp)) return 0; if(!memcmp(id,"MTM",3)) return 1; return 0; } BOOL MTM_Init(void) { mtmtrk=NULL; mh=NULL; if(!(mtmtrk=MyCalloc(64,sizeof(MTMNOTE)))) return 0; if(!(mh=MyCalloc(1,sizeof(MTMHEADER)))) return 0; return 1; } void MTM_Cleanup(void) { if(mtmtrk!=NULL) free(mtmtrk); if(mh!=NULL) free(mh); } UBYTE *MTM_Convert(void) { int t; UBYTE a,b,c,inst,note,eff,dat; UniReset(); for(t=0;t<64;t++){ a=mtmtrk[t].a; b=mtmtrk[t].b; c=mtmtrk[t].c; inst=((a&0x3)<<4)|(b>>4); note=a>>2; eff=b&0xf; dat=c; if(inst!=0){ UniInstrument(inst-1); } if(note!=0){ UniNote(note+24); } /* mtm bug bugfix: when the effect is volslide, slide-up _always_ overrides slide-dn. */ if(eff==0xa && dat&0xf0) dat&=0xf0; UniPTEffect(eff,dat); UniNewline(); } return UniDup(); } BOOL MTM_Load(void) { MTMSAMPLE s; INSTRUMENT *d; SAMPLE *q; int t,u; rewind(modfp); // try to read module header if(!fread(mh,sizeof(MTMHEADER),1,modfp)){ myerr=ERROR_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; for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<<4; of.numins=mh->numsamples; if(!AllocInstruments()) return 0; d=of.instruments; for(t=0;tnumsmp=1; if(!AllocSamples(d)) return 0; q=d->samples; // try to read sample info if(!fread(&s,sizeof(MTMSAMPLE),1,modfp)){ myerr=ERROR_LOADING_SAMPLEINFO; return 0; } d->insname=DupStr(s.samplename,22); q->seekpos=0; q->c2spd=finetune[s.finetune]; q->length=s.length; q->loopstart=s.reppos; q->loopend=s.repend; q->volume=s.volume; q->flags=0; if(s.repend-s.reppos>2) q->flags|=SF_LOOP; // <- 1.00 bugfix 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; } d++; } if(!fread(of.positions,128,1,modfp)){ myerr=ERROR_LOADING_HEADER; return 0; } if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; of.tracks[0]=MTM_Convert(); // track 0 is empty for(t=1;tcommentsize)) return 0; return 1; } LOADER mtmload={ NULL, "MTM", "MTM loader v0.1", MTM_Init, MTM_Test, MTM_Load, MTM_Cleanup };