diff playercode/load_far.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_far.c	Fri Jan 23 16:05:08 1998 +0000
@@ -0,0 +1,288 @@
+/*
+
+ Name: LOAD_FAR.C
+
+ Description:
+ Farandole (FAR) 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 FARSAMPLE
+{   CHAR  samplename[32];
+    ULONG length;
+    UBYTE finetune;
+    UBYTE volume;
+    ULONG reppos;
+    ULONG repend;
+    UBYTE type;
+    UBYTE loop;
+} FARSAMPLE;
+
+
+
+typedef struct FARHEADER1
+{   UBYTE id[4];                        // file magic
+    CHAR  songname[40];                 // songname
+    CHAR  blah[3];                      // 13,10,26
+    UWORD headerlen;                    // remaining length of header in bytes
+    UBYTE version;
+    UBYTE onoff[16];
+    UBYTE edit1[9];
+    UBYTE speed;
+    UBYTE panning[16];
+    UBYTE edit2[4];
+    UWORD stlen;
+} FARHEADER1;
+
+
+typedef struct FARHEADER2
+{   UBYTE orders[256];
+    UBYTE numpat;
+    UBYTE snglen;
+    UBYTE loopto;
+    UWORD patsiz[256];
+} FARHEADER2;
+
+
+typedef struct FARNOTE
+{   UBYTE note,ins,vol,eff;
+} FARNOTE;
+
+
+
+static CHAR FAR_Version[] = "Farandole";
+static FARHEADER1 *mh1 = NULL;
+static FARHEADER2 *mh2 = NULL;
+static FARNOTE *pat = NULL;
+
+
+BOOL FAR_Test(void)
+{
+    UBYTE id[4];
+
+    if(!_mm_read_UBYTES(id,4,modfp)) return 0;
+    return(!memcmp(id,"FAR=",4));
+}
+
+
+BOOL FAR_Init(void)
+{
+    if(!(mh1 = (FARHEADER1 *)_mm_malloc(sizeof(FARHEADER1)))) return 0;
+    if(!(mh2 = (FARHEADER2 *)_mm_malloc(sizeof(FARHEADER2)))) return 0;
+    if(!(pat = (FARNOTE *)_mm_malloc(16*256*sizeof(FARNOTE)))) return 0;
+
+    return 1;
+}
+
+
+void FAR_Cleanup(void)
+{
+    if(mh1!=NULL) free(mh1);
+    if(mh2!=NULL) free(mh2);
+    if(pat!=NULL) free(pat);
+
+    mh1 = NULL;
+    mh2 = NULL;
+    pat = NULL;
+}
+
+
+UBYTE *FAR_ConvertTrack(FARNOTE *n,int rows)
+{
+       int t;
+
+       UniReset();
+
+       for(t=0; t<rows; t++)
+       {   if(n->note)
+           {   UniInstrument(n->ins);
+               UniNote(n->note+23+12);
+           }
+
+           if(n->vol&0xf) UniPTEffect(0xc,(n->vol&0xf)<<2);
+           switch(n->eff>>4)
+           {   case 0xf:
+                  UniPTEffect(0xf,n->eff&0xf);
+               break;
+
+               // others not yet implemented
+           }
+
+           UniNewline();
+           n+=16;
+       }
+       return UniDup();
+}
+
+
+BOOL FAR_Load(void)
+{
+       int t,u,tracks=0;
+       SAMPLE     *q;
+       FARSAMPLE  s;
+       FARNOTE    *crow;
+       UBYTE      smap[8];
+
+       // try to read module header (first part)
+       _mm_read_UBYTES(mh1->id,4,modfp);
+       _mm_read_SBYTES(mh1->songname,40,modfp);
+       _mm_read_SBYTES(mh1->blah,3,modfp);
+       mh1->headerlen = _mm_read_I_UWORD (modfp);
+       mh1->version   = _mm_read_UBYTE (modfp);
+       _mm_read_UBYTES(mh1->onoff,16,modfp);
+       _mm_read_UBYTES(mh1->edit1,9,modfp);
+       mh1->speed     = _mm_read_UBYTE(modfp);
+       _mm_read_UBYTES(mh1->panning,16,modfp);
+       _mm_read_UBYTES(mh1->edit2,4,modfp);
+       mh1->stlen     = _mm_read_I_UWORD (modfp);
+
+
+       // init modfile data
+
+       of.modtype   = strdup(FAR_Version);
+       of.songname  = DupStr(mh1->songname,40);
+       of.numchn    = 16;
+       of.initspeed = mh1->speed;
+       of.inittempo = 99;
+
+       for(t=0; t<16; t++) of.panning[t] = mh1->panning[t]<<4;
+
+       // read songtext into comment field
+       if(!ReadComment(mh1->stlen)) return 0;
+
+       // try to read module header (second part)
+       _mm_read_UBYTES(mh2->orders,256,modfp);
+       mh2->numpat        = _mm_read_UBYTE(modfp);
+       mh2->snglen        = _mm_read_UBYTE(modfp);
+       mh2->loopto        = _mm_read_UBYTE(modfp);
+       _mm_read_I_UWORDS(mh2->patsiz,256,modfp);
+
+//      of.numpat=mh2->numpat;
+       of.numpos = mh2->snglen;
+       if(!AllocPositions(of.numpos)) return 0;
+       for(t=0; t<of.numpos; t++)
+       {   if(mh2->orders[t]==0xff) break;
+           of.positions[t] = mh2->orders[t];
+       }
+
+       // count number of patterns stored in file
+       of.numpat = 0;
+       for(t=0; t<256; t++)
+          if(mh2->patsiz[t]) if((t+1)>of.numpat) of.numpat=t+1;
+
+       of.numtrk = of.numpat*of.numchn;
+
+       // seek across eventual new data
+       _mm_fseek(modfp,mh1->headerlen-(869+mh1->stlen),SEEK_CUR);
+
+       // alloc track and pattern structures
+       if(!AllocTracks()) return 0;
+       if(!AllocPatterns()) return 0;
+
+       for(t=0; t<of.numpat; t++)
+       {   UBYTE rows=0,tempo;
+
+           memset(pat,0,16*256*sizeof(FARNOTE));
+           if(mh2->patsiz[t])
+           {   rows  = _mm_read_UBYTE(modfp);
+               tempo = _mm_read_UBYTE(modfp);
+
+               crow = pat;
+               for(u=mh2->patsiz[t]-2; u; u--, crow++)
+               {   crow->note = _mm_read_UBYTE(modfp);
+                   crow->ins  = _mm_read_UBYTE(modfp);
+                   crow->vol  = _mm_read_UBYTE(modfp);
+                   crow->eff  = _mm_read_UBYTE(modfp);
+               }
+               
+               if(feof(modfp))
+               {   _mm_errno = MMERR_LOADING_PATTERN;
+                   return 0;
+               }
+
+               of.pattrows[t] = rows+2;
+               crow = pat;
+               for(u=16; u; u--)
+                  if(!(of.tracks[tracks++] = FAR_ConvertTrack(crow,rows+2))) return 0;
+           }
+       }
+
+       // read sample map
+       if(!_mm_read_UBYTES(smap,8,modfp))
+       {   _mm_errno = MMERR_LOADING_HEADER;
+           return 0;
+       }
+
+       // count number of samples used
+       of.numins = 0;
+       for(t=0; t<64; t++)
+          if(smap[t>>3] & (1 << (t&7)))  of.numins++;
+       of.numsmp = of.numins;             
+
+       // alloc sample structs
+       if(!AllocSamples()) return 0;
+       q = of.samples;
+
+       for(t=0; t<64; t++)
+       {  if(smap[t>>3] & (1 << (t&7)))
+           {  _mm_read_SBYTES(s.samplename,32,modfp);
+              s.length   = _mm_read_I_ULONG(modfp);
+              s.finetune = _mm_read_UBYTE(modfp);
+              s.volume   = _mm_read_UBYTE(modfp);
+              s.reppos   = _mm_read_I_ULONG(modfp);
+              s.repend   = _mm_read_I_ULONG(modfp);
+              s.type     = _mm_read_UBYTE(modfp);
+              s.loop     = _mm_read_UBYTE(modfp);
+
+              q->samplename = DupStr(s.samplename,32);
+              q->length     = s.length;
+              q->loopstart  = s.reppos;
+              q->loopend    = s.repend;
+              q->volume     = 64;
+              q->speed      = 8363;
+
+              q->flags=SF_SIGNED;
+              if(s.type&1) q->flags|=SF_16BITS;
+              if(s.loop) q->flags|=SF_LOOP;
+
+              q->seekpos = _mm_ftell(modfp);
+              _mm_fseek(modfp,q->length,SEEK_CUR);
+           }
+           q++;
+       }
+       return 1;
+}
+
+
+CHAR *FAR_LoadTitle(void)
+{
+   CHAR s[40];
+
+   _mm_fseek(modfp,4,SEEK_SET);
+   if(!fread(s,40,1,modfp)) return NULL;
+   
+   return(DupStr(s,40));
+}
+
+
+MLOADER load_far =
+{   NULL,
+    "FAR",
+    "Portable FAR loader v0.1",
+    FAR_Init,
+    FAR_Test,
+    FAR_Load,
+    FAR_Cleanup,
+    FAR_LoadTitle
+};
+