#include #include #include #include #include "mloader.h" #include "munitrk.h" typedef struct DSMNOTE{ UBYTE note,ins,vol,cmd,inf; } DSMNOTE; typedef struct DSMINST{ UBYTE filename[13]; UWORD flags; UBYTE volume; ULONG length; ULONG loopstart; ULONG loopend; ULONG reserved1; UWORD c2spd; UWORD reserved2; UBYTE samplename[28]; } DSMINST; typedef struct DSMSONG{ char songname[28]; UWORD reserved1; UWORD flags; ULONG reserved2; UWORD numord; UWORD numsmp; UWORD numpat; UWORD numtrk; UBYTE globalvol; UBYTE mastervol; UBYTE speed; UBYTE bpm; UBYTE panpos[16]; UBYTE orders[128]; } DSMSONG; #define MOTLONG(a,b,c,d) (((ULONG)d<<24)|((ULONG)c<<16)|((ULONG)b<<8)|a) #define SONGID MOTLONG('S','O','N','G') #define INSTID MOTLONG('I','N','S','T') #define PATTID MOTLONG('P','A','T','T') ULONG blockid; ULONG blockln; ULONG blocklp; static DSMSONG *mh; DSMNOTE *dsmbuf; char DSM_Version[]="DSIK DSM-format"; BOOL DSM_Test(void) { char id[12]; rewind(modfp); if(!fread(id,12,1,modfp)) return 0; if(!memcmp(id,"RIFF",4) && !memcmp(&id[8],"DSMF",4)) return 1; return 0; } BOOL DSM_Init(void) { dsmbuf=NULL; mh=NULL; if(!(dsmbuf=(DSMNOTE *)MyMalloc(16*64*sizeof(DSMNOTE)))) return 0; if(!(mh=(DSMSONG *)MyCalloc(1,sizeof(DSMSONG)))) return 0; return 1; } void DSM_Cleanup(void) { if(dsmbuf!=NULL) free(dsmbuf); if(mh!=NULL) free(mh); } BOOL GetBlockHeader(void) { /* make sure we're at the right position for reading the next riff block, no matter how many bytes read */ fseek(modfp,blocklp+blockln,SEEK_SET); while(1){ if(!fread(&blockid,sizeof(ULONG),1,modfp) || !fread(&blockln,sizeof(ULONG),1,modfp)){ myerr=ERROR_LOADING_HEADER; return 0; } if(blockid!=SONGID && blockid!=INSTID && blockid!=PATTID ){ printf("Skipping unknown block type %4.4s\n",&blockid); fseek(modfp,blockln,SEEK_CUR); } else break; } blocklp=ftell(modfp); return 1; } BOOL DSM_ReadPattern(void) { int row=0,flag; DSMNOTE *n; // clear pattern data memset(dsmbuf,255,16*64*sizeof(DSMNOTE)); fgetc(modfp); fgetc(modfp); while(row<64){ flag=fgetc(modfp); if(flag==EOF){ myerr=ERROR_LOADING_PATTERN; return 0; } if(flag){ n=&dsmbuf[((flag&0xf)*64)+row]; if(flag&0x80) n->note=fgetc(modfp); if(flag&0x40) n->ins=fgetc(modfp); if(flag&0x20) n->vol=fgetc(modfp); if(flag&0x10){ n->cmd=fgetc(modfp); n->inf=fgetc(modfp); } } else row++; } return 1; } UBYTE *DSM_ConvertTrack(DSMNOTE *tr) { int t; UBYTE note,ins,vol,cmd,inf; UniReset(); for(t=0;t<64;t++){ note=tr[t].note; ins=tr[t].ins; vol=tr[t].vol; cmd=tr[t].cmd; inf=tr[t].inf; if(ins!=0 && ins!=255){ UniInstrument(ins-1); } if(note!=255){ UniNote(note-1); // <- normal note } if(vol<65){ UniPTEffect(0xc,vol); } if(cmd!=255){ if(cmd==0x8){ if(inf<=0x80){ inf=(inf<0x80) ? inf<<1 : 255; UniPTEffect(cmd,inf); } } else if(cmd==0xb){ if(inf<=0x7f) UniPTEffect(cmd,inf); } else UniPTEffect(cmd,inf); } UniNewline(); } return UniDup(); } BOOL DSM_Load(void) { int t; DSMINST s; INSTRUMENT *d; SAMPLE *q; int cursmp=0,curpat=0,track=0; blocklp=0; blockln=12; if(!GetBlockHeader()) return 0; if(blockid!=SONGID){ myerr=ERROR_LOADING_HEADER; return 0; } if(!fread(mh,sizeof(DSMSONG),1,modfp)){ myerr=ERROR_LOADING_HEADER; return 0; } /* set module variables */ of.initspeed=mh->speed; of.inittempo=mh->bpm; of.modtype=strdup(DSM_Version); of.numchn=mh->numtrk; of.numpat=mh->numpat; of.numtrk=of.numchn*of.numpat; of.songname=DupStr(mh->songname,28); // make a cstr of songname for(t=0;t<16;t++){ of.panning[t]=mh->panpos[t]<0x80 ? (mh->panpos[t]<<1) : 255; } of.numpos=0; for(t=0;tnumord;t++){ of.positions[of.numpos]=mh->orders[t]; if(mh->orders[t]<254) of.numpos++; } of.numins=mh->numsmp; if(!AllocInstruments()) return 0; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; while(cursmpnumsmp=1; if(!AllocSamples(d)) return 0; q=d->samples; // try to read sample info if(!fread(&s,sizeof(DSMINST),1,modfp)){ myerr=ERROR_LOADING_SAMPLEINFO; return 0; } d->insname=DupStr(s.samplename,28); q->seekpos=ftell(modfp); q->c2spd=s.c2spd; q->length=s.length; q->loopstart=s.loopstart; q->loopend=s.loopend; q->volume=s.volume; q->flags=0; if(s.flags&1) q->flags|=SF_LOOP; if(s.flags&2) q->flags|=SF_SIGNED; cursmp++; } else if(blockid==PATTID && curpat