diff playercode/load_ult.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_ult.c	Fri Jan 23 16:05:08 1998 +0000
@@ -0,0 +1,292 @@
+/*
+
+ Name:  LOAD_ULT.C
+
+ Description:
+ Ultratracker (ULT) 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"
+
+
+#define ULTS_16BITS     4
+#define ULTS_LOOP       8
+#define ULTS_REVERSE    16
+
+
+// Raw ULT header struct:
+
+typedef struct ULTHEADER
+{   CHAR  id[16];
+    CHAR  songtitle[32];
+    UBYTE reserved;
+} ULTHEADER;
+
+
+// Raw ULT sampleinfo struct:
+
+typedef struct ULTSAMPLE
+{   CHAR   samplename[32];
+    CHAR   dosname[12];
+    SLONG  loopstart;
+    SLONG  loopend;
+    SLONG  sizestart;
+    SLONG  sizeend;
+    UBYTE  volume;
+    UBYTE  flags;
+    SWORD  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[16];
+
+    if(!_mm_read_string(id,15,modfp)) return 0;
+    return(!strncmp(id,"MAS_UTrack_V00",14));
+}
+
+
+BOOL ULT_Init(void)
+{
+    return 1;
+}
+
+
+void ULT_Cleanup(void)
+{
+}
+
+ULTEVENT ev;
+
+
+
+int ReadUltEvent(ULTEVENT *event)
+{
+    UBYTE flag,rep=1;
+
+    flag = _mm_read_UBYTE(modfp);
+
+    if(flag==0xfc)
+    {   rep = _mm_read_UBYTE(modfp);
+        event->note =_mm_read_UBYTE(modfp);
+    } else
+        event->note = flag;
+
+    event->sample   =_mm_read_UBYTE(modfp);
+    event->eff      =_mm_read_UBYTE(modfp);
+    event->dat1     =_mm_read_UBYTE(modfp);
+    event->dat2     =_mm_read_UBYTE(modfp);
+
+    return rep;
+}
+
+
+BOOL ULT_Load(void)
+{
+    int        t,u,tracks=0;
+    SAMPLE     *q;
+    ULTSAMPLE  s;
+    ULTHEADER  mh;
+    UBYTE      nos,noc,nop;
+
+    // try to read module header
+
+    _mm_read_string(mh.id,15,modfp);
+    _mm_read_string(mh.songtitle,32,modfp);
+    mh.reserved = _mm_read_UBYTE(modfp);
+
+    if(feof(modfp))
+    {   _mm_errno = MMERR_LOADING_HEADER;
+        return 0;
+    }
+
+    if(mh.id[14]<'1' || mh.id[14]>'4')
+    {   _mm_errno = MMERR_NOT_A_MODULE;
+        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;
+
+    nos = _mm_read_UBYTE(modfp);
+
+    if(feof(modfp))
+    {   _mm_errno = MMERR_LOADING_HEADER;
+        return 0;
+    }
+
+    of.songname = DupStr(mh.songtitle,32);
+    of.numins   = nos;
+
+    if(!AllocSamples()) return 0;
+    
+    q = of.samples;
+
+    for(t=0; t<nos; t++)
+    {   // try to read sample info
+
+        _mm_read_string(s.samplename,32,modfp);
+        _mm_read_string(s.dosname,12,modfp);
+        s.loopstart     =_mm_read_I_ULONG(modfp);
+        s.loopend       =_mm_read_I_ULONG(modfp);
+        s.sizestart     =_mm_read_I_ULONG(modfp);
+        s.sizeend       =_mm_read_I_ULONG(modfp);
+        s.volume        =_mm_read_UBYTE(modfp);
+        s.flags         =_mm_read_UBYTE(modfp);
+        s.finetune      =_mm_read_I_SWORD(modfp);
+
+        if(feof(modfp))
+        {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
+            return 0;
+        }
+
+        q->samplename = DupStr(s.samplename,32);
+        q->speed      = 8363;
+
+        if(mh.id[14]>='4')
+        {   _mm_read_I_UWORD(modfp);       // read 1.6 extra info(??) word
+            q->speed=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;
+        }
+
+        q++;
+    }
+
+    if(!AllocPositions(256)) return 0;
+    for(t=0; t<256; t++)
+        of.positions[t] = _mm_read_UBYTE(modfp);
+    for(t=0; t<256; t++)
+        if(of.positions[t]==255) break;
+
+    of.numpos = t;
+
+    noc = _mm_read_UBYTE(modfp);
+    nop = _mm_read_UBYTE(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<of.numchn; u++)
+    {   for(t=0; t<of.numpat; t++)
+            of.patterns[(t*of.numchn)+u]=tracks++;
+    }
+
+    // read pan position table for v1.5 and higher
+
+    if(mh.id[14]>='3')
+        for(t=0; t<of.numchn; t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
+
+    for(t=0; t<of.numtrk; t++)
+    {   int rep,s,done;
+
+        UniReset();
+        done=0;
+
+        while(done<64)
+        {   rep=ReadUltEvent(&ev);
+
+            if(feof(modfp))
+            {   _mm_errno = MMERR_LOADING_TRACK;
+                return 0;
+            }
+
+            for(s=0; s<rep; s++)
+            {   UBYTE eff;
+
+                if(ev.sample) UniInstrument(ev.sample-1);
+                if(ev.note)   UniNote(ev.note+23);
+
+                eff = ev.eff>>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++;
+            }
+        }
+        if(!(of.tracks[t]=UniDup())) return 0;
+    }
+
+    return 1;
+}
+
+
+CHAR *ULT_LoadTitle(void)
+{
+   CHAR s[32];
+
+   _mm_fseek(modfp,15,SEEK_SET);
+   if(!fread(s,32,1,modfp)) return NULL;
+   
+   return(DupStr(s,32));
+}
+
+
+MLOADER load_ult =
+{   NULL,
+    "ULT",
+    "Portable ULT loader v0.1",
+    ULT_Init,
+    ULT_Test,
+    ULT_Load,
+    ULT_Cleanup,
+    ULT_LoadTitle
+};
+