#include #include #include #include #include "mloader.h" #include "munitrk.h" /************************************************************************* *************************************************************************/ typedef struct MSAMPINFO{ // sample header as it appears in a module UBYTE samplename[22]; UWORD length; UBYTE finetune; UBYTE volume; UWORD reppos; UWORD replen; } MSAMPINFO; typedef struct MODULEHEADER{ // verbatim module header UBYTE songname[20]; // the songname.. MSAMPINFO samples[15]; // all sampleinfo UBYTE songlength; // number of patterns used UBYTE magic1; // should be 127 UBYTE positions[128]; // which pattern to play at pos } MODULEHEADER; typedef struct MODNOTE{ UBYTE a,b,c,d; } MODNOTE; #define rword(p) ((((p)<<8)&0xff00) | (((p)>>8)&0x00ff)) #define cword(p) p=rword(p) /************************************************************************* *************************************************************************/ static MODULEHEADER *mh; // raw as-is module header static MODNOTE *patbuf; BOOL M15_Test(void) { int t; MODULEHEADER mh; fseek(modfp,0,SEEK_SET); if(!fread(&mh,sizeof(MODULEHEADER),1,modfp)) return 0; for(t=0;t<15;t++){ // all finetunes should be zero if(mh.samples[t].finetune!=0) return 0; // all volumes should be <=64 if(mh.samples[t].volume>64) return 0; } if(mh.magic1>127) return 0; // and magic1 should be <128 return 1; } BOOL M15_Init(void) { patbuf=NULL; if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0; return 1; } void M15_Cleanup(void) { if(mh!=NULL) free(mh); if(patbuf!=NULL) free(patbuf); } /* Old (amiga) noteinfo: _____byte 1_____ byte2_ _____byte 3_____ byte4_ / \ / \ / \ / \ 0000 0000-00000000 0000 0000-00000000 Upper four 12 bits for Lower four Effect command. bits of sam- note period. bits of sam- ple number. ple number. */ UWORD M15_npertab[60]={ // -> Tuning 0 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906, 856,808,762,720,678,640,604,570,538,508,480,453, 428,404,381,360,339,320,302,285,269,254,240,226, 214,202,190,180,170,160,151,143,135,127,120,113, 107,101,95,90,85,80,75,71,67,63,60,56 }; void M15_ConvertNote(MODNOTE *n) { UBYTE instrument,effect,effdat,note; UWORD period; /* extract the various information from the 4 bytes that make up a single note */ instrument=(n->a&0x10)|(n->c>>4); period=(((UWORD)n->a&0xf)<<8)+n->b; effect=n->c&0xf; effdat=n->d; // Convert the period to a note number note=0; if(period!=0){ for(note=0;note<60;note++){ if(period>=M15_npertab[note]) break; } note++; if(note==61) note=0; } if(instrument!=0){ UniInstrument(instrument-1); } if(note!=0){ UniNote(note+23); } UniPTEffect(effect,effdat); } UBYTE *M15_ConvertTrack(MODNOTE *n) { int t; UniReset(); for(t=0;t<64;t++){ M15_ConvertNote(n); UniNewline(); n+=of.numchn; } return UniDup(); } BOOL M15_LoadPatterns(void) /* Loads all patterns of a modfile and converts them into the 3 byte format. */ { int t,s,tracks=0; if(!AllocPatterns()) return 0; if(!AllocTracks()) return 0; /* Allocate temporary buffer for loading and converting the patterns */ if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0; for(t=0;tsamples[t].length); cword(mh->samples[t].reppos); cword(mh->samples[t].replen); } /* set module variables */ of.initspeed=6; of.inittempo=125; of.numchn=4; // get number of channels of.modtype=strdup("15-instrument"); // get ascii type of mod of.songname=DupStr(mh->songname,20); // make a cstr of songname of.numpos=mh->songlength; // copy the songlength memcpy(of.positions,mh->positions,128); // copy the position array /* Count the number of patterns */ of.numpat=0; for(t=0;t<128;t++){ // <-- BUGFIX... have to check ALL positions if(of.positions[t] > of.numpat){ of.numpat=of.positions[t]; } } of.numpat++; of.numtrk=of.numpat*of.numchn; // Finally, init the sampleinfo structures of.numins=15; if(!AllocInstruments()) return 0; s=mh->samples; // init source pointer d=of.instruments; // init dest pointer for(t=0;tnumsmp=1; if(!AllocSamples(d)) return 0; q=d->samples; // convert the samplename d->insname=DupStr(s->samplename,22); /* init the sampleinfo variables and convert the size pointers to longword format */ q->c2spd=finetune[s->finetune&0xf]; q->volume=s->volume; q->loopstart=s->reppos; q->loopend=q->loopstart+(s->replen<<1); q->length=s->length<<1; q->seekpos=0; q->flags=SF_SIGNED; if(s->replen>1) q->flags|=SF_LOOP; /* fix replen if repend>length */ if(q->loopend>q->length) q->loopend=q->length; s++; // point to next source sampleinfo d++; // point to next destiny sampleinfo } if(!M15_LoadPatterns()) return 0; return 1; } LOADER m15load={ NULL, "15-instrument module", "MOD-15 loader v0.1", M15_Init, M15_Test, M15_Load, M15_Cleanup };