7 Ultratracker (ULT) module loader
10 All systems - all compilers (hopefully)
21 #define ULTS_REVERSE 16
24 /* Raw ULT header struct: */
26 typedef struct ULTHEADER{
33 /* Raw ULT sampleinfo struct: */
35 typedef struct ULTSAMPLE{
48 typedef struct ULTEVENT{
49 UBYTE note,sample,eff,dat1,dat2;
65 if(!fread(&id,15,1,modfp)) return 0;
66 return(!strncmp(id,"MAS_UTrack_V00",14));
76 void ULT_Cleanup(void)
84 int ReadUltEvent(ULTEVENT *event)
88 flag=_mm_read_UBYTE(modfp);
91 fread(&rep,1,1,modfp);
92 event->note =_mm_read_UBYTE(modfp);
98 event->sample =_mm_read_UBYTE(modfp);
99 event->eff =_mm_read_UBYTE(modfp);
100 event->dat1 =_mm_read_UBYTE(modfp);
101 event->dat2 =_mm_read_UBYTE(modfp);
118 /* try to read module header */
120 _mm_read_str(mh.id,15,modfp);
121 _mm_read_str(mh.songtitle,32,modfp);
122 mh.reserved=_mm_read_UBYTE(modfp);
125 myerr=ERROR_LOADING_HEADER;
129 if(mh.id[14]<'1' || mh.id[14]>'4'){
130 printf("This version is not yet supported\n");
134 of.modtype=strdup(ULT_Version[mh.id[14]-'1']);
140 if(!ReadComment((UWORD)mh.reserved*32)) return 0;
142 nos=_mm_read_UBYTE(modfp);
145 myerr=ERROR_LOADING_HEADER;
149 of.songname=DupStr(mh.songtitle,32);
152 if(!AllocInstruments()) return 0;
159 if(!AllocSamples(d)) return 0;
162 /* try to read sample info */
164 _mm_read_str(s.samplename,32,modfp);
165 _mm_read_str(s.dosname,12,modfp);
166 s.loopstart =_mm_read_I_ULONG(modfp);
167 s.loopend =_mm_read_I_ULONG(modfp);
168 s.sizestart =_mm_read_I_ULONG(modfp);
169 s.sizeend =_mm_read_I_ULONG(modfp);
170 s.volume =_mm_read_UBYTE(modfp);
171 s.flags =_mm_read_UBYTE(modfp);
172 s.finetune =_mm_read_I_SWORD(modfp);
175 myerr=ERROR_LOADING_SAMPLEINFO;
179 d->insname=DupStr(s.samplename,32);
186 _mm_read_I_UWORD(modfp); /* read 1.6 extra info(??) word */
190 q->length=s.sizeend-s.sizestart;
191 q->volume=s.volume>>2;
192 q->loopstart=s.loopstart;
193 q->loopend=s.loopend;
197 if(s.flags&ULTS_LOOP){
201 if(s.flags&ULTS_16BITS){
207 /* printf("Sample %d %s length %ld\n",t,d->samplename,d->length); */
211 _mm_read_UBYTES(of.positions,256,modfp);
214 if(of.positions[t]==255) break;
218 noc=_mm_read_UBYTE(modfp);
219 nop=_mm_read_UBYTE(modfp);
223 of.numtrk=of.numchn*of.numpat;
225 if(!AllocTracks()) return 0;
226 if(!AllocPatterns()) return 0;
228 for(u=0;u<of.numchn;u++){
229 for(t=0;t<of.numpat;t++){
230 of.patterns[(t*of.numchn)+u]=tracks++;
234 /* read pan position table for v1.5 and higher */
237 for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
241 for(t=0;t<of.numtrk;t++){
249 rep=ReadUltEvent(&ev);
252 myerr=ERROR_LOADING_TRACK;
256 /* printf("rep %d: n %d i %d e %x d1 %d d2 %d \n",rep,ev.note,ev.sample,ev.eff,ev.dat1,ev.dat2); */
264 UniInstrument(ev.sample-1);
275 ULT panning effect fixed by Alexander Kerkhove :
279 if(eff==0xc) UniPTEffect(eff,ev.dat2>>2);
280 else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf);
281 else UniPTEffect(eff,ev.dat2);
285 if(eff==0xc) UniPTEffect(eff,ev.dat1>>2);
286 else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf);
287 else UniPTEffect(eff,ev.dat1);
293 /* printf("----------------"); */
295 if(!(of.tracks[t]=UniDup())) return 0;
298 /* printf("%d channels %d patterns\n",of.numchn,of.numpat); */
299 /* printf("Song %32.32s: There's %d samples\n",mh.songtitle,nos); */
308 "Portable ULT loader v0.1",