diff playercode/load_dsm.c @ 4:5d614bcc4287

Initial entry of mikmod into the CVS tree.
author darius
date Fri, 23 Jan 1998 16:05:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/playercode/load_dsm.c	Fri Jan 23 16:05:08 1998 +0000
@@ -0,0 +1,314 @@
+/*
+
+ 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
+};
+