#include #include #include #include #include "mloader.h" #include "munitrk.h" #define ULTS_16BITS 4 #define ULTS_LOOP 8 #define ULTS_REVERSE 16 // Raw ULT header struct: typedef struct ULTHEADER{ char id[15]; char songtitle[32]; char reserved; } ULTHEADER; // Raw ULT sampleinfo struct: typedef struct ULTSAMPLE{ char samplename[32]; char dosname[12]; LONG loopstart; LONG loopend; LONG sizestart; LONG sizeend; UBYTE volume; UBYTE flags; WORD finetune; } ULTSAMPLE; typedef struct ULTEVENT{ UBYTE note,sample,eff,dat1,dat2; } ULTEVENT; char *ULT_Version[]={ "Ultra Tracker V1.3", "Ultra Tracker V1.4", "Ultra Tracker V1.5", "Ultra Tracker V1.6" }; BOOL ULT_Test(void) { char id[15]; rewind(modfp); if(!fread(&id,15,1,modfp)) return 0; return(!strncmp(id,"MAS_UTrack_V00",14)); } BOOL ULT_Init(void) { return 1; } void ULT_Cleanup(void) { } ULTEVENT ev; BOOL ReadUltEvent(ULTEVENT *event) { UBYTE flag,rep; if(!fread(&flag,1,1,modfp)) return 0; if(flag==0xfc){ fread(&rep,1,1,modfp); if(fread(event,sizeof(ULTEVENT),1,modfp)) return rep; } else{ event->note=flag; if(fread(&event->sample,sizeof(ULTEVENT)-1,1,modfp)) return 1; } return 0; } BOOL ULT_Load(void) { int t,u,tracks=0; UWORD dummy; INSTRUMENT *d; SAMPLE *q; ULTSAMPLE s; ULTHEADER mh; UBYTE nos,noc,nop; rewind(modfp); // try to read module header if(!fread(&mh,sizeof(ULTHEADER),1,modfp)){ myerr=ERROR_LOADING_HEADER; return 0; } if(mh.id[14]<'1' || mh.id[14]>'4'){ printf("This version is not yet supported\n"); return 0; } of.modtype=strdup(ULT_Version[mh.id[14]-'1']); of.initspeed=6; of.inittempo=125; // read songtext if(!ReadComment((UWORD)mh.reserved*32)) return 0; if(!fread(&nos,1,1,modfp)){ myerr=ERROR_LOADING_HEADER; return 0; } of.songname=DupStr(mh.songtitle,32); of.numins=nos; if(!AllocInstruments()) return 0; d=of.instruments; for(t=0;tnumsmp=1; if(!AllocSamples(d)) return 0; q=d->samples; // try to read sample info if(!fread(&s,sizeof(ULTSAMPLE),1,modfp)){ myerr=ERROR_LOADING_SAMPLEINFO; return 0; } d->insname=DupStr(s.samplename,32); /* printf("%s ss %ld se %ld ls %ld le %ld\n", d->samplename, s.sizestart, s.sizeend, s.loopstart, s.loopend); */ q->seekpos=0; q->c2spd=8363; if(mh.id[14]>='4'){ fread(&dummy,sizeof(UWORD),1,modfp); // read 1.6 extra info(??) word q->c2spd=s.finetune; } q->length=s.sizeend-s.sizestart; q->volume=s.volume>>2; q->loopstart=s.loopstart; q->loopend=s.loopend; q->flags=SF_SIGNED; if(s.flags&ULTS_LOOP){ q->flags|=SF_LOOP; } if(s.flags&ULTS_16BITS){ q->flags|=SF_16BITS; q->loopstart>>=1; q->loopend>>=1; } // printf("Sample %d %s length %ld\n",t,d->samplename,d->length); d++; } fread(of.positions,256,1,modfp); for(t=0;t<256;t++){ if(of.positions[t]==255) break; } of.numpos=t; fread(&noc,1,1,modfp); fread(&nop,1,1,modfp); of.numchn=noc+1; of.numpat=nop+1; of.numtrk=of.numchn*of.numpat; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; for(u=0;u='3'){ for(t=0;t>4; /* ULT panning effect fixed by Alexander Kerkhove : */ if(eff==0xc) UniPTEffect(eff,ev.dat2>>2); else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf); else UniPTEffect(eff,ev.dat2); eff=ev.eff&0xf; if(eff==0xc) UniPTEffect(eff,ev.dat1>>2); else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf); else UniPTEffect(eff,ev.dat1); UniNewline(); done++; } } // printf("----------------"); if(!(of.tracks[t]=UniDup())) return 0; } // printf("%d channels %d patterns\n",of.numchn,of.numpat); // printf("Song %32.32s: There's %d samples\n",mh.songtitle,nos); return 1; } LOADER ultload={ NULL, "ULT", "ULT loader v0.1", ULT_Init, ULT_Test, ULT_Load, ULT_Cleanup };