Mercurial > ~darius > hgwebdir.cgi > mikmod
view playercode/load_mtm.c @ 7:de95ce2eacfd
Initial revision
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:09 +0000 |
parents | 5d614bcc4287 |
children |
line wrap: on
line source
/* 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 };