7 15 instrument MOD loader
10 All systems - all compilers (hopefully)
19 /*************************************************************************
20 *************************************************************************/
23 typedef struct MSAMPINFO{ /* sample header as it appears in a module */
33 typedef struct MODULEHEADER{ /* verbatim module header */
34 char songname[20]; /* the songname.. */
35 MSAMPINFO samples[15]; /* all sampleinfo */
36 UBYTE songlength; /* number of patterns used */
37 UBYTE magic1; /* should be 127 */
38 UBYTE positions[128]; /* which pattern to play at pos */
42 typedef struct MODNOTE{
47 /*************************************************************************
48 *************************************************************************/
50 static MODULEHEADER *mh; /* raw as-is module header */
51 static MODNOTE *patbuf;
54 static BOOL LoadModuleHeader(MODULEHEADER *mh)
58 _mm_read_str(mh->songname,20,modfp);
61 MSAMPINFO *s= &mh->samples[t];
62 _mm_read_str(s->samplename,22,modfp);
63 s->length =_mm_read_M_UWORD(modfp);
64 s->finetune =_mm_read_UBYTE(modfp);
65 s->volume =_mm_read_UBYTE(modfp);
66 s->reppos =_mm_read_M_UWORD(modfp);
67 s->replen =_mm_read_M_UWORD(modfp);
70 mh->songlength =_mm_read_UBYTE(modfp);
71 mh->magic1 =_mm_read_UBYTE(modfp); /* should be 127 */
72 _mm_read_UBYTES(mh->positions,128,modfp);
84 if(!LoadModuleHeader(&mh)) return 0;
88 /* all finetunes should be zero */
89 if(mh.samples[t].finetune!=0) return 0;
91 /* all volumes should be <=64 */
92 if(mh.samples[t].volume>64) return 0;
94 if(mh.magic1>127) return 0; /* and magic1 should be <128 */
103 if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
108 void M15_Cleanup(void)
110 if(mh!=NULL) free(mh);
111 if(patbuf!=NULL) free(patbuf);
117 Old (amiga) noteinfo:
119 _____byte 1_____ byte2_ _____byte 3_____ byte4_
121 0000 0000-00000000 0000 0000-00000000
123 Upper four 12 bits for Lower four Effect command.
124 bits of sam- note period. bits of sam-
125 ple number. ple number.
131 UWORD M15_npertab[60]={
135 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
136 856,808,762,720,678,640,604,570,538,508,480,453,
137 428,404,381,360,339,320,302,285,269,254,240,226,
138 214,202,190,180,170,160,151,143,135,127,120,113,
139 107,101,95,90,85,80,75,71,67,63,60,56
143 void M15_ConvertNote(MODNOTE *n)
145 UBYTE instrument,effect,effdat,note;
148 /* extract the various information from the 4 bytes that
149 make up a single note */
151 instrument=(n->a&0x10)|(n->c>>4);
152 period=(((UWORD)n->a&0xf)<<8)+n->b;
156 /* Convert the period to a note number */
160 for(note=0;note<60;note++){
161 if(period>=M15_npertab[note]) break;
168 UniInstrument(instrument-1);
175 UniPTEffect(effect,effdat);
180 UBYTE *M15_ConvertTrack(MODNOTE *n)
195 BOOL M15_LoadPatterns(void)
197 Loads all patterns of a modfile and converts them into the
203 if(!AllocPatterns()) return 0;
204 if(!AllocTracks()) return 0;
206 /* Allocate temporary buffer for loading
207 and converting the patterns */
209 if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
211 for(t=0;t<of.numpat;t++){
213 /* Load the pattern into the temp buffer
216 for(s=0;s<(64U*of.numchn);s++){
217 patbuf[s].a=_mm_read_UBYTE(modfp);
218 patbuf[s].b=_mm_read_UBYTE(modfp);
219 patbuf[s].c=_mm_read_UBYTE(modfp);
220 patbuf[s].d=_mm_read_UBYTE(modfp);
223 for(s=0;s<of.numchn;s++){
224 if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
236 INSTRUMENT *d; /* new sampleinfo structure */
238 MSAMPINFO *s; /* old module sampleinfo */
240 /* try to read module header */
242 if(!LoadModuleHeader(mh)){
243 myerr=ERROR_LOADING_HEADER;
247 /* set module variables */
251 of.numchn=4; /* get number of channels */
252 of.modtype=strdup("15-instrument"); /* get ascii type of mod */
253 of.songname=DupStr(mh->songname,20); /* make a cstr of songname */
254 of.numpos=mh->songlength; /* copy the songlength */
255 memcpy(of.positions,mh->positions,128); /* copy the position array */
257 /* Count the number of patterns */
261 for(t=0;t<128;t++){ /* <-- BUGFIX... have to check ALL positions */
262 if(of.positions[t] > of.numpat){
263 of.numpat=of.positions[t];
267 of.numtrk=of.numpat*of.numchn;
269 /* Finally, init the sampleinfo structures */
272 if(!AllocInstruments()) return 0;
274 s=mh->samples; /* init source pointer */
275 d=of.instruments; /* init dest pointer */
277 for(t=0;t<of.numins;t++){
280 if(!AllocSamples(d)) return 0;
284 /* convert the samplename */
286 d->insname=DupStr(s->samplename,22);
288 /* init the sampleinfo variables and
289 convert the size pointers to longword format */
291 q->c2spd=finetune[s->finetune&0xf];
293 q->loopstart=s->reppos;
294 q->loopend=q->loopstart+(s->replen<<1);
295 q->length=s->length<<1;
299 if(s->replen>1) q->flags|=SF_LOOP;
301 /* fix replen if repend>length */
303 if(q->loopend>q->length) q->loopend=q->length;
305 s++; /* point to next source sampleinfo */
306 d++; /* point to next destiny sampleinfo */
309 if(!M15_LoadPatterns()) return 0;
317 "15-instrument module",
318 "Portable MOD-15 loader v0.1",