Mercurial > ~darius > hgwebdir.cgi > mikmod
diff playercode/load_mtm.c @ 4:5d614bcc4287
Initial entry of mikmod into the CVS tree.
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/playercode/load_mtm.c Fri Jan 23 16:05:08 1998 +0000 @@ -0,0 +1,282 @@ +/* + + Name: LOAD_MTM.C + + Description: + MTM module loader + + Portability: + All systems - all compilers (hopefully) + + If this module is found to not be portable to any particular platform, + please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for + more information on contacting the author). + +*/ + +#include <string.h> +#include "mikmod.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 = NULL; +static MTMNOTE *mtmtrk = NULL; +static UWORD pat[32]; + +char MTM_Version[] = "MTM"; + + + +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_calloc(1,sizeof(MTMHEADER)))) return 0; + + return 1; +} + + +void MTM_Cleanup(void) +{ + if(mtmtrk!=NULL) free(mtmtrk); + if(mh!=NULL) free(mh); + + mtmtrk = NULL; + mh = NULL; +} + + +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; + + // Convert pattern jump from Dec to Hex + if(eff == 0xd) + dat = (((dat&0xf0)>>4)*10)+(dat&0xf); + UniPTEffect(eff,dat); + UniNewline(); + } + return UniDup(); +} + + +BOOL MTM_Load(void) +{ + MTMSAMPLE s; + SAMPLE *q; + + int t,u; + + // 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; + 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(!ReadComment(mh->commentsize)) 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)); +} + + +MLOADER load_mtm = +{ NULL, + "MTM", + "Portable MTM loader v0.1", + MTM_Init, + MTM_Test, + MTM_Load, + MTM_Cleanup, + MTM_LoadTitle +}; +