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[31]; /* 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 */
39 UBYTE magic2[4]; /* string "M.K." or "FLT4" or "FLT8" */
42 #define MODULEHEADERSIZE 1084
45 typedef struct MODTYPE{ /* struct to identify type of module */
52 typedef struct MODNOTE{
57 /*************************************************************************
58 *************************************************************************/
61 char protracker[]="Protracker";
62 char startracker[]="Startracker";
63 char fasttracker[]="Fasttracker";
64 char ins15tracker[]="15-instrument";
65 char oktalyzer[]="Oktalyzer";
66 char taketracker[]="TakeTracker";
70 "M.K.",4,protracker, /* protracker 4 channel */
71 "M!K!",4,protracker, /* protracker 4 channel */
72 "FLT4",4,startracker, /* startracker 4 channel */
73 "4CHN",4,fasttracker, /* fasttracker 4 channel */
74 "6CHN",6,fasttracker, /* fasttracker 6 channel */
75 "8CHN",8,fasttracker, /* fasttracker 8 channel */
76 "CD81",8,oktalyzer, /* atari oktalyzer 8 channel */
77 "OKTA",8,oktalyzer, /* atari oktalyzer 8 channel */
78 "16CN",16,taketracker, /* taketracker 16 channel */
79 "32CN",32,taketracker, /* taketracker 32 channel */
80 " ",4,ins15tracker /* 15-instrument 4 channel */
83 static MODULEHEADER *mh; /* raw as-is module header */
84 static MODNOTE *patbuf;
93 _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
94 if(!fread(id,4,1,modfp)) return 0;
96 /* find out which ID string */
99 if(!memcmp(id,modtypes[t].id,4)) return 1;
109 if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
114 void MOD_Cleanup(void)
116 if(mh!=NULL) free(mh);
117 if(patbuf!=NULL) free(patbuf);
123 Old (amiga) noteinfo:
125 _____byte 1_____ byte2_ _____byte 3_____ byte4_
127 0000 0000-00000000 0000 0000-00000000
129 Upper four 12 bits for Lower four Effect command.
130 bits of sam- note period. bits of sam-
131 ple number. ple number.
141 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
142 856,808,762,720,678,640,604,570,538,508,480,453,
143 428,404,381,360,339,320,302,285,269,254,240,226,
144 214,202,190,180,170,160,151,143,135,127,120,113,
145 107,101,95,90,85,80,75,71,67,63,60,56
149 void ConvertNote(MODNOTE *n)
151 UBYTE instrument,effect,effdat,note;
154 /* extract the various information from the 4 bytes that
155 make up a single note */
157 instrument=(n->a&0x10)|(n->c>>4);
158 period=(((UWORD)n->a&0xf)<<8)+n->b;
162 /* Convert the period to a note number */
166 for(note=0;note<60;note++){
167 if(period>=npertab[note]) break;
174 UniInstrument(instrument-1);
181 UniPTEffect(effect,effdat);
185 UBYTE *ConvertTrack(MODNOTE *n)
199 BOOL ML_LoadPatterns(void)
201 Loads all patterns of a modfile and converts them into the
207 if(!AllocPatterns()) return 0;
208 if(!AllocTracks()) return 0;
210 /* Allocate temporary buffer for loading
211 and converting the patterns */
213 if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
215 for(t=0;t<of.numpat;t++){
217 /* Load the pattern into the temp buffer
220 for(s=0;s<(64U*of.numchn);s++){
221 patbuf[s].a=_mm_read_UBYTE(modfp);
222 patbuf[s].b=_mm_read_UBYTE(modfp);
223 patbuf[s].c=_mm_read_UBYTE(modfp);
224 patbuf[s].d=_mm_read_UBYTE(modfp);
227 for(s=0;s<of.numchn;s++){
228 if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
239 INSTRUMENT *d; /* new sampleinfo structure */
241 MSAMPINFO *s; /* old module sampleinfo */
243 /* try to read module header */
245 _mm_read_str((char *)mh->songname,20,modfp);
249 _mm_read_str(s->samplename,22,modfp);
250 s->length =_mm_read_M_UWORD(modfp);
251 s->finetune =_mm_read_UBYTE(modfp);
252 s->volume =_mm_read_UBYTE(modfp);
253 s->reppos =_mm_read_M_UWORD(modfp);
254 s->replen =_mm_read_M_UWORD(modfp);
257 mh->songlength =_mm_read_UBYTE(modfp);
258 mh->magic1 =_mm_read_UBYTE(modfp);
260 _mm_read_UBYTES(mh->positions,128,modfp);
261 _mm_read_UBYTES(mh->magic2,4,modfp);
264 myerr=ERROR_LOADING_HEADER;
268 /* find out which ID string */
270 for(modtype=0;modtype<10;modtype++){
271 if(!memcmp(mh->magic2,modtypes[modtype].id,4)) break;
276 /* unknown modtype */
277 myerr=ERROR_NOT_A_MODULE;
281 /* set module variables */
285 of.numchn=modtypes[modtype].channels; /* get number of channels */
286 of.modtype=strdup(modtypes[modtype].name); /* get ascii type of mod */
287 of.songname=DupStr(mh->songname,20); /* make a cstr of songname */
288 of.numpos=mh->songlength; /* copy the songlength */
289 memcpy(of.positions,mh->positions,128); /* copy the position array */
291 /* Count the number of patterns */
295 for(t=0;t<128;t++){ /* <-- BUGFIX... have to check ALL positions */
296 if(of.positions[t] > of.numpat){
297 of.numpat=of.positions[t];
301 of.numtrk=of.numpat*of.numchn;
303 /* Finally, init the sampleinfo structures */
307 if(!AllocInstruments()) return 0;
309 s=mh->samples; /* init source pointer */
310 d=of.instruments; /* init dest pointer */
312 for(t=0;t<of.numins;t++){
315 if(!AllocSamples(d)) return 0;
319 /* convert the samplename */
321 d->insname=DupStr(s->samplename,22);
323 /* init the sampleinfo variables and
324 convert the size pointers to longword format */
326 q->c2spd=finetune[s->finetune&0xf];
328 q->loopstart=(ULONG)s->reppos<<1;
329 q->loopend=q->loopstart+((ULONG)s->replen<<1);
330 q->length=(ULONG)s->length<<1;
334 if(s->replen>1) q->flags|=SF_LOOP;
336 /* fix replen if repend>length */
338 if(q->loopend>q->length) q->loopend=q->length;
340 s++; /* point to next source sampleinfo */
341 d++; /* point to next destiny sampleinfo */
344 if(!ML_LoadPatterns()) return 0;
353 "Portable MOD loader v0.11",