--- /dev/null
+/*\r
+\r
+Name:\r
+MLOADER.C\r
+\r
+Description:\r
+These routines are used to access the available module loaders\r
+\r
+Portability:\r
+All systems - all compilers\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "mikmod.h"\r
+\r
+\r
+FILE *modfp;\r
+UNIMOD of;\r
+\r
+LOADER *firstloader=NULL;\r
+\r
+\r
+UWORD finetune[16]={\r
+ 8363, 8413, 8463, 8529, 8581, 8651, 8723, 8757,\r
+ 7895, 7941, 7985, 8046, 8107, 8169, 8232, 8280\r
+};\r
+\r
+\r
+\r
+\r
+\r
+void ML_InfoLoader(void)\r
+{\r
+ int t;\r
+ LOADER *l;\r
+\r
+ /* list all registered devicedrivers: */\r
+\r
+ for(t=1,l=firstloader; l!=NULL; l=l->next, t++){\r
+ printf("%d. %s\n",t,l->version);\r
+ }\r
+}\r
+\r
+\r
+void ML_RegisterLoader(LOADER *ldr)\r
+{\r
+ LOADER *l;\r
+\r
+ if(firstloader==NULL){\r
+ firstloader=ldr;\r
+ ldr->next=NULL;\r
+ }\r
+ else{\r
+ ldr->next=firstloader;\r
+ firstloader=ldr;\r
+ }\r
+}\r
+\r
+\r
+\r
+void *MyMalloc(size_t size)\r
+/*\r
+ Same as malloc, but sets error variable ml_errno when it failed\r
+*/\r
+{\r
+ void *d;\r
+\r
+ d=malloc(size);\r
+ if(d==NULL){\r
+ myerr="Error allocating structure";\r
+ }\r
+ return d;\r
+}\r
+\r
+\r
+\r
+void *MyCalloc(size_t nitems,size_t size)\r
+/*\r
+ Same as calloc, but sets error variable ml_errno when it failed\r
+*/\r
+{\r
+ void *d;\r
+\r
+ d=calloc(nitems,size);\r
+ if(d==NULL){\r
+ myerr="Error allocating structure";\r
+ }\r
+ return d;\r
+}\r
+\r
+\r
+\r
+BOOL ReadComment(UWORD len)\r
+{\r
+ int t;\r
+\r
+ if(len){\r
+ if(!(of.comment=(char *)MyMalloc(len+1))) return 0;\r
+ fread(of.comment,len,1,modfp);\r
+ of.comment[len]=0;\r
+\r
+ /* strip any control-characters in the comment: */\r
+\r
+ for(t=0;t<len;t++){\r
+ if(of.comment[t]<32) of.comment[t]=' ';\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+\r
+BOOL AllocPatterns(void)\r
+{\r
+ int s,t,tracks=0;\r
+\r
+ /* Allocate track sequencing array */\r
+\r
+ if(!(of.patterns=(UWORD *)MyCalloc((ULONG)of.numpat*of.numchn,sizeof(UWORD)))) return 0;\r
+ if(!(of.pattrows=(UWORD *)MyCalloc(of.numpat,sizeof(UWORD)))) return 0;\r
+\r
+ for(t=0;t<of.numpat;t++){\r
+\r
+ of.pattrows[t]=64;\r
+\r
+ for(s=0;s<of.numchn;s++){\r
+ of.patterns[(t*of.numchn)+s]=tracks++;\r
+ }\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+BOOL AllocTracks(void)\r
+{\r
+ if(!(of.tracks=(UBYTE **)MyCalloc(of.numtrk,sizeof(UBYTE *)))) return 0;\r
+ return 1;\r
+}\r
+\r
+\r
+\r
+BOOL AllocInstruments(void)\r
+{\r
+ UWORD t;\r
+\r
+ if(!(of.instruments=(INSTRUMENT *)MyCalloc(of.numins,sizeof(INSTRUMENT)))) return 0;\r
+ return 1;\r
+}\r
+\r
+\r
+BOOL AllocSamples(INSTRUMENT *i)\r
+{\r
+ UWORD u,n;\r
+\r
+ if(n=i->numsmp){\r
+ if(!(i->samples=(SAMPLE *)MyCalloc(n,sizeof(SAMPLE)))) return 0;\r
+\r
+ for(u=0; u<n; u++){\r
+ i->samples[u].panning=128;\r
+ i->samples[u].handle=-1;\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+char *DupStr(char *s,UWORD len)\r
+/*\r
+ Creates a CSTR out of a character buffer of 'len' bytes, but strips\r
+ any terminating non-printing characters like 0, spaces etc.\r
+*/\r
+{\r
+ UWORD t;\r
+ char *d=NULL;\r
+\r
+ /* Scan for first printing char in buffer [includes high ascii up to 254] */\r
+\r
+ while(len){\r
+ if(!(s[len-1]>=0 && s[len-1]<=0x20)) break;\r
+ len--;\r
+ }\r
+\r
+ if(len){\r
+\r
+ /* When the buffer wasn't completely empty, allocate\r
+ a cstring and copy the buffer into that string, except\r
+ for any control-chars */\r
+\r
+ if((d=(char *)malloc(len+1))!=NULL){\r
+ for(t=0;t<len;t++) {\r
+ d[t]=(s[t]>=0 && s[t]<32) ? ' ': s[t];\r
+ }\r
+ d[t]=0;\r
+ }\r
+ }\r
+\r
+ return d;\r
+}\r
+\r
+\r
+\r
+BOOL ML_LoadSamples(void)\r
+{\r
+ UWORD t,u;\r
+ INSTRUMENT *i;\r
+ SAMPLE *s;\r
+\r
+ for(t=0;t<of.numins;t++){\r
+\r
+ i=&of.instruments[t];\r
+\r
+ for(u=0; u<i->numsmp; u++){\r
+\r
+ s=&i->samples[u];\r
+\r
+/* printf("Loading Sample %d\n",t); */\r
+\r
+ /* sample has to be loaded ? -> increase\r
+ number of samples and allocate memory and\r
+ load sample */\r
+\r
+ if(s->length){\r
+\r
+ if(s->seekpos){\r
+ _mm_fseek(modfp,s->seekpos,SEEK_SET);\r
+ }\r
+\r
+ /* Call the sample load routine of the driver module.\r
+ It has to return a 'handle' (>=0) that identifies\r
+ the sample */\r
+\r
+ s->handle=MD_SampleLoad(modfp,\r
+ s->length,\r
+ s->loopstart,\r
+ s->loopend,\r
+ s->flags);\r
+\r
+ if(s->handle<0) return 0;\r
+ }\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+BOOL ML_LoadHeader(void)\r
+{\r
+ BOOL ok=0;\r
+ LOADER *l;\r
+\r
+ /* Try to find a loader that recognizes the module */\r
+\r
+ for(l=firstloader; l!=NULL; l=l->next){\r
+ _mm_rewind(modfp);\r
+ if(l->Test()) break;\r
+ }\r
+\r
+ if(l==NULL){\r
+ myerr="Unknown module format.";\r
+ return 0;\r
+ }\r
+\r
+ /* init unitrk routines */\r
+\r
+ if(!UniInit()) return 0;\r
+\r
+ /* init module loader */\r
+\r
+ if(l->Init()){\r
+ _mm_rewind(modfp);\r
+ ok=l->Load();\r
+ }\r
+\r
+ l->Cleanup();\r
+\r
+ /* free unitrk allocations */\r
+\r
+ UniCleanup();\r
+ return ok;\r
+}\r
+\r
+\r
+\r
+void ML_XFreeInstrument(INSTRUMENT *i)\r
+{\r
+ UWORD t;\r
+\r
+ if(i->samples!=NULL){\r
+ for(t=0; t<i->numsmp; t++){\r
+ if(i->samples[t].handle>=0){\r
+ MD_SampleUnLoad(i->samples[t].handle);\r
+ }\r
+ }\r
+ free(i->samples);\r
+ }\r
+ if(i->insname!=NULL) free(i->insname);\r
+}\r
+\r
+\r
+void ML_FreeEx(UNIMOD *mf)\r
+{\r
+ UWORD t;\r
+\r
+ if(mf->modtype!=NULL) free(mf->modtype);\r
+ if(mf->patterns!=NULL) free(mf->patterns);\r
+ if(mf->pattrows!=NULL) free(mf->pattrows);\r
+\r
+ if(mf->tracks!=NULL){\r
+ for(t=0;t<mf->numtrk;t++){\r
+ if(mf->tracks[t]!=NULL) free(mf->tracks[t]);\r
+ }\r
+ free(mf->tracks);\r
+ }\r
+\r
+ if(mf->instruments!=NULL){\r
+ for(t=0;t<mf->numins;t++){\r
+ ML_XFreeInstrument(&mf->instruments[t]);\r
+ }\r
+ free(mf->instruments);\r
+ }\r
+\r
+ if(mf->songname!=NULL) free(mf->songname);\r
+ if(mf->comment!=NULL) free(mf->comment);\r
+}\r
+\r
+\r
+\r
+/******************************************\r
+\r
+ Next are the user-callable functions\r
+\r
+******************************************/\r
+\r
+\r
+void ML_Free(UNIMOD *mf)\r
+{\r
+ if(mf!=NULL){\r
+ ML_FreeEx(mf);\r
+ free(mf);\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+UNIMOD *ML_LoadFP(FILE *fp)\r
+{\r
+ int t;\r
+ UNIMOD *mf;\r
+\r
+ /* init fileptr, clear errorcode, clear static modfile: */\r
+\r
+ modfp=fp;\r
+ myerr=NULL;\r
+ memset(&of,0,sizeof(UNIMOD));\r
+\r
+ /* init panning array */\r
+\r
+ for(t=0;t<32;t++){\r
+ of.panning[t]=((t+1)&2)?255:0;\r
+ }\r
+\r
+ if(!ML_LoadHeader()){\r
+ ML_FreeEx(&of);\r
+ return NULL;\r
+ }\r
+\r
+ if(!ML_LoadSamples()){\r
+ ML_FreeEx(&of);\r
+ return NULL;\r
+ }\r
+\r
+ if(!(mf=(UNIMOD *)MyCalloc(1,sizeof(UNIMOD)))){\r
+ ML_FreeEx(&of);\r
+ return NULL;\r
+ }\r
+\r
+ /* Copy the static UNIMOD contents\r
+ into the dynamic UNIMOD struct */\r
+\r
+ memcpy(mf,&of,sizeof(UNIMOD));\r
+\r
+ return mf;\r
+}\r
+\r
+\r
+\r
+UNIMOD *ML_LoadFN(char *filename)\r
+{\r
+ FILE *fp;\r
+ UNIMOD *mf;\r
+\r
+ if((fp=fopen(filename,"rb"))==NULL){\r
+ myerr="Error opening file";\r
+ return NULL;\r
+ }\r
+\r
+ mf=ML_LoadFP(fp);\r
+ fclose(fp);\r
+\r
+ return mf;\r
+}\r
+\r