diff playercode/load_mod.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_mod.c	Fri Jan 23 16:05:08 1998 +0000
@@ -0,0 +1,341 @@
+/*
+
+ Name: LOAD_MOD.C
+
+ Description:
+ Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
+
+ 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 MSAMPINFO                  // sample header as it appears in a module
+{   CHAR  samplename[22];
+    UWORD length;
+    UBYTE finetune;
+    UBYTE volume;
+    UWORD reppos;
+    UWORD replen;
+} MSAMPINFO;
+
+
+typedef struct MODULEHEADER              // verbatim module header
+{   CHAR       songname[20];             // the songname..
+    MSAMPINFO  samples[31];              // all sampleinfo
+    UBYTE      songlength;               // number of patterns used
+    UBYTE      magic1;                   // should be 127
+    UBYTE      positions[128];           // which pattern to play at pos
+    UBYTE      magic2[4];                // string "M.K." or "FLT4" or "FLT8"
+} MODULEHEADER;
+
+#define MODULEHEADERSIZE 1084
+
+
+typedef struct MODTYPE              // struct to identify type of module
+{   CHAR    id[5];
+    UBYTE   channels;
+    CHAR    *name;
+} MODTYPE;
+
+
+typedef struct MODNOTE
+{   UBYTE a,b,c,d;
+} MODNOTE;
+
+
+/*************************************************************************
+*************************************************************************/
+
+
+CHAR protracker[]   = "Protracker";
+CHAR startracker[]  = "Startracker";
+CHAR fasttracker[]  = "Fasttracker";
+CHAR ins15tracker[] = "15-instrument";
+CHAR oktalyzer[]    = "Oktalyzer";
+CHAR taketracker[]  = "TakeTracker";
+
+
+MODTYPE modtypes[] =
+{   "M.K.",4,protracker,      // protracker 4 channel
+    "M!K!",4,protracker,      // protracker 4 channel
+    "FLT4",4,startracker,     // startracker 4 channel
+    "2CHN",2,fasttracker,     // fasttracker 2 channel
+    "4CHN",4,fasttracker,     // fasttracker 4 channel
+    "6CHN",6,fasttracker,     // fasttracker 6 channel
+    "8CHN",8,fasttracker,     // fasttracker 8 channel
+    "10CH",10,fasttracker,    // fasttracker 10 channel
+    "12CH",12,fasttracker,    // fasttracker 12 channel
+    "14CH",14,fasttracker,    // fasttracker 14 channel
+    "16CH",16,fasttracker,    // fasttracker 16 channel
+    "18CH",18,fasttracker,    // fasttracker 18 channel
+    "20CH",20,fasttracker,    // fasttracker 20 channel
+    "22CH",22,fasttracker,    // fasttracker 22 channel
+    "24CH",24,fasttracker,    // fasttracker 24 channel
+    "26CH",26,fasttracker,    // fasttracker 26 channel
+    "28CH",28,fasttracker,    // fasttracker 28 channel
+    "30CH",30,fasttracker,    // fasttracker 30 channel
+    "32CH",32,fasttracker,    // fasttracker 32 channel
+    "CD81",8,oktalyzer,       // atari oktalyzer 8 channel
+    "OKTA",8,oktalyzer,       // atari oktalyzer 8 channel
+    "16CN",16,taketracker,    // taketracker 16 channel
+    "32CN",32,taketracker,    // taketracker 32 channel
+    "    ",4,ins15tracker     // 15-instrument 4 channel    
+};
+
+static MODULEHEADER *mh = NULL;        // raw as-is module header
+static MODNOTE *patbuf = NULL;
+static int modtype = 0;
+
+BOOL MOD_Test(void)
+{
+    UBYTE id[4];
+
+    _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
+    if(!fread(id,4,1,modfp)) return 0;
+
+    // find out which ID string
+
+    for(modtype=0; modtype<23; modtype++)
+        if(!memcmp(id,modtypes[modtype].id,4)) return 1;
+
+    return 0;
+}
+
+
+BOOL MOD_Init(void)
+{
+    if(!(mh=(MODULEHEADER *)_mm_calloc(1,sizeof(MODULEHEADER)))) return 0;
+    return 1;
+}
+
+
+void MOD_Cleanup(void)
+{
+    if(mh!=NULL) free(mh);
+    if(patbuf!=NULL) free(patbuf);
+
+    mh = NULL;
+    patbuf = NULL;
+}
+
+
+/*
+Old (amiga) noteinfo:
+
+ _____byte 1_____   byte2_    _____byte 3_____   byte4_
+/                \ /      \  /                \ /      \
+0000          0000-00000000  0000          0000-00000000
+
+Upper four    12 bits for    Lower four    Effect command.
+bits of sam-  note period.   bits of sam-
+ple number.                  ple number.
+
+*/
+
+
+void ConvertNote(MODNOTE *n)
+{
+    UBYTE instrument,effect,effdat,note;
+    UWORD period;
+
+    // extract the various information from the 4 bytes that
+    // make up a single note
+
+    instrument = (n->a&0x10)|(n->c>>4);
+    period     = (((UWORD)n->a&0xf)<<8)+n->b;
+    effect     = n->c&0xf;
+    effdat     = n->d;
+
+    // Convert the period to a note number
+
+    note=0;
+    if(period!=0)
+    {   for(note=0; note<60; note++)
+            if(period >= npertab[note]) break;
+        note++;
+        if(note==61) note = 0;
+    }
+
+    if(instrument!=0) UniInstrument(instrument-1);
+    if(note!=0) UniNote(note+23);
+
+    // Convert pattern jump from Dec to Hex
+    if(effect == 0xd)
+        effdat = (((effdat&0xf0)>>4)*10)+(effdat&0xf);
+
+    UniPTEffect(effect,effdat);
+}
+
+
+UBYTE *ConvertTrack(MODNOTE *n)
+{
+    int t;
+
+    UniReset();
+    for(t=0;t<64;t++)
+    {   ConvertNote(n);
+        UniNewline();
+        n+=of.numchn;
+    }
+    return UniDup();
+}
+
+
+BOOL ML_LoadPatterns(void)
+//  Loads all patterns of a modfile and converts them into the
+//  3 byte format.
+{
+    int t,s,tracks = 0;
+
+    if(!AllocPatterns()) return 0;
+    if(!AllocTracks())   return 0;
+
+    // Allocate temporary buffer for loading
+    // and converting the patterns
+
+    if(!(patbuf=(MODNOTE *)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
+
+    for(t=0; t<of.numpat; t++)
+    {   // Load the pattern into the temp buffer
+        // and convert it
+
+        for(s=0; s<(64U*of.numchn); s++)
+        {   patbuf[s].a = _mm_read_UBYTE(modfp);
+            patbuf[s].b = _mm_read_UBYTE(modfp);
+            patbuf[s].c = _mm_read_UBYTE(modfp);
+            patbuf[s].d = _mm_read_UBYTE(modfp);
+        }
+
+        for(s=0; s<of.numchn; s++)
+            if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
+    }
+
+    return 1;
+}
+
+
+BOOL MOD_Load(void)
+{
+    int       t;
+    SAMPLE    *q;
+    MSAMPINFO *s;           // old module sampleinfo
+
+    // try to read module header
+
+    _mm_read_string((CHAR *)mh->songname,20,modfp);
+
+    for(t=0; t<31; t++)
+    {   s = &mh->samples[t];
+        _mm_read_string(s->samplename,22,modfp);
+        s->length   =_mm_read_M_UWORD(modfp);
+        s->finetune =_mm_read_UBYTE(modfp);
+        s->volume   =_mm_read_UBYTE(modfp);
+        s->reppos   =_mm_read_M_UWORD(modfp);
+        s->replen   =_mm_read_M_UWORD(modfp);
+    }
+
+    mh->songlength  =_mm_read_UBYTE(modfp);
+    mh->magic1      =_mm_read_UBYTE(modfp);
+
+    _mm_read_UBYTES(mh->positions,128,modfp);
+    _mm_read_UBYTES(mh->magic2,4,modfp);
+
+    if(feof(modfp))
+    {   _mm_errno = MMERR_LOADING_HEADER;
+        return 0;
+    }
+
+    // set module variables
+
+    of.initspeed = 6;
+    of.inittempo = 125;
+    of.numchn    = modtypes[modtype].channels;      // get number of channels
+    of.modtype   = strdup(modtypes[modtype].name);  // get ascii type of mod
+    of.songname  = DupStr(mh->songname,20);         // make a cstr of songname
+    of.numpos    = mh->songlength;                  // copy the songlength
+
+    if(!AllocPositions(of.numpos)) return 0;
+    for(t=0; t<of.numpos; t++)
+        of.positions[t] = mh->positions[t];
+
+    // Count the number of patterns
+
+    of.numpat = 0;
+
+    for(t=0; t<of.numpos; t++)
+    {   if(of.positions[t] > of.numpat)
+            of.numpat = of.positions[t];
+    }
+    of.numpat++;
+    of.numtrk = of.numpat*of.numchn;
+    
+    // Finally, init the sampleinfo structures 
+    of.numins = of.numsmp = 31;
+
+    if(!AllocSamples())     return 0;
+    
+    s = mh->samples;       // init source pointer 
+    q = of.samples;
+    
+    for(t=0; t<of.numins; t++)
+    {   // convert the samplename
+        q->samplename = DupStr(s->samplename, 22);
+
+        // init the sampleinfo variables and
+        // convert the size pointers to longword format
+
+        q->speed     = finetune[s->finetune & 0xf];
+        q->volume    = s->volume;
+        q->loopstart = (ULONG)s->reppos << 1;
+        q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
+        q->length    = (ULONG)s->length << 1;
+
+        q->flags     = SF_SIGNED;
+        if(s->replen > 1) q->flags |= SF_LOOP;
+
+        // fix replen if repend > length
+        if(q->loopend > q->length) q->loopend = q->length;
+
+        s++;    // point to next source sampleinfo
+        q++;
+    }
+
+    if(!ML_LoadPatterns()) return 0;
+    return 1;
+}
+
+
+CHAR *MOD_LoadTitle(void)
+{
+   CHAR s[20];
+
+   _mm_fseek(modfp,0,SEEK_SET);
+   if(!fread(s,20,1,modfp)) return NULL;
+   
+   return(DupStr(s,20));
+}
+
+
+MLOADER load_mod =
+{   NULL,
+    "Standard module",
+    "Portable MOD loader v0.11",
+    MOD_Init,
+    MOD_Test,
+    MOD_Load,
+    MOD_Cleanup,
+    MOD_LoadTitle
+};
+