home *** CD-ROM | disk | FTP | other *** search
- /* MikMod sound library
- (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*==============================================================================
-
- $Id: load_mod.c,v 1.17 1998/12/07 06:00:17 miod Exp $
-
- Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
-
- ==============================================================================*/
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #include <string.h>
-
- #include <mikmod_internals.h>
-
- /*========== Module structure */
-
- typedef struct MSAMPINFO {
- CHAR samplename[23]; /* 22 in module, 23 in memory */
- UWORD length;
- UBYTE finetune;
- UBYTE volume;
- UWORD reppos;
- UWORD replen;
- } MSAMPINFO;
-
- typedef struct MODULEHEADER {
- CHAR songname[21]; /* the songname.. 20 in module, 21 in memory */
- 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;
-
- typedef struct MODTYPE {
- CHAR id[5];
- UBYTE channels;
- CHAR *name;
- } MODTYPE;
-
- typedef struct MODNOTE {
- UBYTE a,b,c,d;
- } MODNOTE;
-
- /*========== Loader variables */
-
- #define MODULEHEADERSIZE 1084
-
- CHAR protracker[] = "Protracker";
- CHAR startracker[] = "Startracker";
- CHAR fasttracker[] = "Fasttracker";
- CHAR ins15tracker[] = "15-instrument";
- CHAR oktalyzer[] = "Oktalyzer";
- CHAR taketracker[] = "TakeTracker";
-
- #define MODTYPE_COUNT 24
- MODTYPE modtypes[MODTYPE_COUNT+1]={
- {"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 */
- {"15CH",15, fasttracker}, /* fasttracker 15 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;
- static MODNOTE *patbuf = NULL;
- static int modtype = 0;
-
- /*========== Loader code */
-
- 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<MODTYPE_COUNT;modtype++)
- if(!memcmp(id,modtypes[modtype].id,4)) return 1;
-
- return 0;
- }
-
- BOOL MOD_Init(void)
- {
- if( !(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
- return 1;
- }
-
- void MOD_Cleanup(void)
- {
- if(mh) free(mh);
- if(patbuf) 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;
- UBYTE lastnote=0;
-
- /* extract the various information from the 4 bytes that make up a 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) {
- for(note=0;note<7*OCTAVE;note++)
- if(period>=npertab[note]) break;
- note++;
- if(note==7*OCTAVE+1) note=0;
- }
-
- if(instrument) {
- UniInstrument(instrument-1);
- if(!note) note=lastnote;
- }
- if(note) {
- UniNote(note+2*OCTAVE-1);
- lastnote=note;
- }
-
- /* Convert pattern jump from Dec to Hex */
- if(effect==0xd)
- effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
-
- /* finetune conversion to Lxx */
- if(effect==5)
- S3MIT_ProcessCmd(0xc,effdat,1);
- else
- UniPTEffect(effect,effdat);
- }
-
- UBYTE* ConvertTrack(MODNOTE* n)
- {
- int t;
-
- UniReset();
- for(t=0;t<64;t++) {
- ConvertNote(n);
- UniNewline();
- n+=of.numchn;
- }
- return UniDup();
- }
-
- /* Loads all patterns of a modfile and converts them into the 3 byte format. */
- BOOL ML_LoadPatterns(void)
- {
- 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(BOOL curious)
- {
- int t,scan;
- SAMPLE *q;
- MSAMPINFO *s;
-
- /* try to read module header */
- _mm_read_string((CHAR*)mh->songname,20,modfp);
- mh->songname[20]=0; /* just in case */
-
- for(t=0;t<31;t++) {
- s=&mh->samples[t];
- _mm_read_string(s->samplename,22,modfp);
- s->samplename[22]=0; /* just in case */
- 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;
- of.modtype = strdup(modtypes[modtype].name);
- of.songname = DupStr(mh->songname,21);
- of.numpos = mh->songlength;
- of.reppos = 0;
-
- /* Count the number of patterns */
- of.numpat = 0;
- for(t=0;t<of.numpos;t++)
- if(mh->positions[t]>of.numpat)
- of.numpat=mh->positions[t];
- /* since some old modules embed extra patterns, we have to check the
- whole list to get the samples' file offsets right - however we can find
- garbage here, so check carefully */
- scan=1;
- for(t=of.numpos;t<128;t++)
- if(mh->positions[t]>=0x80) scan=0;
- if (scan)
- for(t=of.numpos;t<128;t++) {
- if(mh->positions[t]>of.numpat)
- of.numpat=mh->positions[t];
- if((curious)&&(mh->positions[t])) of.numpos=t+1;
- }
- of.numpat++;
- of.numtrk = of.numpat*of.numchn;
-
- if(!AllocPositions(of.numpos)) return 0;
- for(t=0;t<of.numpos;t++)
- of.positions[t]=mh->positions[t];
-
- /* Finally, init the sampleinfo structures */
- of.numins=of.numsmp=31;
- if(!AllocSamples()) return 0;
- s = mh->samples;
- q = of.samples;
- for(t=0;t<of.numins;t++) {
- /* convert the samplename */
- q->samplename = DupStr(s->samplename, 23);
- /* init the sampleinfo variables and convert the size pointers */
- 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++;
- q++;
- }
-
- if(!ML_LoadPatterns()) return 0;
- return 1;
- }
-
- CHAR *MOD_LoadTitle(void)
- {
- CHAR s[21];
-
- _mm_fseek(modfp,0,SEEK_SET);
- if(!fread(s,20,1,modfp)) return NULL;
- s[20]=0; /* just in case */
-
- return(DupStr(s,21));
- }
-
- /*========== Loader information */
-
- MLOADER load_mod={
- NULL,
- "Standard module",
- "MOD loader v1.0",
- MOD_Init,
- MOD_Test,
- MOD_Load,
- MOD_Cleanup,
- MOD_LoadTitle
- };
-