Mercurial > ~darius > hgwebdir.cgi > mikmod
view playercode/load_far.c @ 11:d5cb2cfc8eca
Initial revision
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:11 +0000 |
parents | 5d614bcc4287 |
children |
line wrap: on
line source
/* 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 };