Mercurial > ~darius > hgwebdir.cgi > mikmod
view playercode/load_dsm.c @ 7:de95ce2eacfd
Initial revision
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:09 +0000 |
parents | 5d614bcc4287 |
children |
line wrap: on
line source
/* Name: LOAD_DSM.C Description: DSIK Internal Format (DSM) module loader Portability: All systems - all compilers (hopefully) If this module is found to not be portable to any particular platform, please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for more information on contacting the author). */ #include <string.h> #include "mikmod.h" typedef struct DSMNOTE { UBYTE note,ins,vol,cmd,inf; } DSMNOTE; typedef struct DSMINST { CHAR filename[13]; UWORD flags; UBYTE volume; ULONG length; ULONG loopstart; ULONG loopend; ULONG reserved1; UWORD c2spd; UWORD reserved2; CHAR 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; static CHAR *SONGID = "SONG"; static CHAR *INSTID = "INST"; static CHAR *PATTID = "PATT"; static UBYTE blockid[4]; static ULONG blockln; static ULONG blocklp; static DSMSONG *mh = NULL; static DSMNOTE *dsmbuf = NULL; static CHAR DSM_Version[] = "DSIK DSM-format"; BOOL DSM_Test(void) { UBYTE id[12]; if(_mm_read_UBYTES((UBYTE *)id,12,modfp)) return 0; if(!memcmp(id,"RIFF",4) && !memcmp(&id[8],"DSMF",4)) return 1; return 0; } BOOL DSM_Init(void) { if(!(dsmbuf=(DSMNOTE *)_mm_malloc(16*64*sizeof(DSMNOTE)))) return 0; if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0; return 1; } void DSM_Cleanup(void) { if(dsmbuf!=NULL) free(dsmbuf); if(mh!=NULL) free(mh); dsmbuf = NULL; mh = NULL; } BOOL GetBlockHeader(void) { // make sure we're at the right position for reading the // next riff block, no matter how many bytes read _mm_fseek(modfp, blocklp+blockln, SEEK_SET); while(1) { _mm_read_UBYTES(blockid,4,modfp); blockln = _mm_read_I_ULONG(modfp); if(feof(modfp)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) && memcmp(blockid,PATTID,4)) { //printf("Skipping unknown block type %4.4s\n",&blockid); _mm_fseek(modfp, blockln, SEEK_CUR); } else break; } blocklp = _mm_ftell(modfp); return 1; } BOOL DSM_ReadPattern(void) { int row=0,flag; DSMNOTE *n; // clear pattern data memset(dsmbuf,255,16*64*sizeof(DSMNOTE)); _mm_read_UBYTE(modfp); _mm_read_UBYTE(modfp); while(row<64) { flag = _mm_read_UBYTE(modfp); if(feof(modfp)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } if(flag) { n = &dsmbuf[((flag&0xf)*64)+row]; if(flag&0x80) n->note = _mm_read_UBYTE(modfp); if(flag&0x40) n->ins = _mm_read_UBYTE(modfp); if(flag&0x20) n->vol = _mm_read_UBYTE(modfp); if(flag&0x10) { n->cmd = _mm_read_UBYTE(modfp); n->inf = _mm_read_UBYTE(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 { // Convert pattern jump from Dec to Hex if(cmd == 0xd) inf = (((inf&0xf0)>>4)*10)+(inf&0xf); UniPTEffect(cmd,inf); } } UniNewline(); } return UniDup(); } BOOL DSM_Load(void) { int t; DSMINST s; SAMPLE *q; int cursmp = 0, curpat = 0, track = 0; blocklp = 0; blockln = 12; if(!GetBlockHeader()) return 0; if(memcmp(blockid,SONGID,4)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } _mm_read_UBYTES(mh->songname,28,modfp); mh->reserved1 = _mm_read_I_UWORD(modfp); mh->flags = _mm_read_I_UWORD(modfp); mh->reserved2 = _mm_read_I_ULONG(modfp); mh->numord = _mm_read_I_UWORD(modfp); mh->numsmp = _mm_read_I_UWORD(modfp); mh->numpat = _mm_read_I_UWORD(modfp); mh->numtrk = _mm_read_I_UWORD(modfp); mh->globalvol = _mm_read_UBYTE(modfp); mh->mastervol = _mm_read_UBYTE(modfp); mh->speed = _mm_read_UBYTE(modfp); mh->bpm = _mm_read_UBYTE(modfp); _mm_read_UBYTES(mh->panpos,16,modfp); _mm_read_UBYTES(mh->orders,128,modfp); // 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; if(!AllocPositions(mh->numord)) return 0; of.numpos = 0; for(t=0; t<mh->numord; t++) { of.positions[of.numpos] = mh->orders[t]; if(mh->orders[t]<254) of.numpos++; } of.numins = of.numsmp = mh->numsmp; if(!AllocSamples()) return 0; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; while(cursmp<of.numins || curpat<of.numpat) { if(!GetBlockHeader()) return 0; if(!memcmp(blockid,INSTID,4) && cursmp<of.numins) { q = &of.samples[cursmp]; // try to read sample info _mm_read_UBYTES(s.filename,13,modfp); s.flags = _mm_read_I_UWORD(modfp); s.volume = _mm_read_UBYTE(modfp); s.length = _mm_read_I_ULONG(modfp); s.loopstart = _mm_read_I_ULONG(modfp); s.loopend = _mm_read_I_ULONG(modfp); s.reserved1 = _mm_read_I_ULONG(modfp); s.c2spd = _mm_read_I_UWORD(modfp); s.reserved2 = _mm_read_I_UWORD(modfp); _mm_read_UBYTES(s.samplename,28,modfp); q->samplename= DupStr(s.samplename,28); q->seekpos = _mm_ftell(modfp); q->speed = s.c2spd; q->length = s.length; q->loopstart = s.loopstart; q->loopend = s.loopend; q->volume = s.volume; if(s.flags&1) q->flags|=SF_LOOP; if(s.flags&2) q->flags|=SF_SIGNED; cursmp++; } else if(!memcmp(blockid,PATTID,4) && curpat<of.numpat) { DSM_ReadPattern(); for(t=0; t<of.numchn; t++) if(!(of.tracks[track++] = DSM_ConvertTrack(&dsmbuf[t*64]))) return 0; curpat++; } } return 1; } CHAR *DSM_LoadTitle(void) { CHAR s[28]; _mm_fseek(modfp,12,SEEK_SET); if(!fread(s,28,1,modfp)) return NULL; return(DupStr(s,28)); } MLOADER load_dsm = { NULL, "DSM", "Portable DSM loader v0.1", DSM_Init, DSM_Test, DSM_Load, DSM_Cleanup, DSM_LoadTitle };