Mercurial > ~darius > hgwebdir.cgi > mikmod
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 +}; +