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