6e135fc5ae5dba689f8a55fa3059bd4d164beb46
[dosdemo] / libs / oldmik / src / mloader.c
1 /*\r
2 \r
3 Name:\r
4 MLOADER.C\r
5 \r
6 Description:\r
7 These routines are used to access the available module loaders\r
8 \r
9 Portability:\r
10 All systems - all compilers\r
11 \r
12 */\r
13 #include <stdio.h>\r
14 #include <stdlib.h>\r
15 #include <string.h>\r
16 #include "mikmod.h"\r
17 \r
18 \r
19 FILE *modfp;\r
20 UNIMOD of;\r
21 \r
22 LOADER *firstloader=NULL;\r
23 \r
24 \r
25 UWORD finetune[16]={\r
26         8363,   8413,   8463,   8529,   8581,   8651,   8723,   8757,\r
27         7895,   7941,   7985,   8046,   8107,   8169,   8232,   8280\r
28 };\r
29 \r
30 \r
31 \r
32 \r
33 \r
34 void ML_InfoLoader(void)\r
35 {\r
36         int t;\r
37         LOADER *l;\r
38 \r
39         /* list all registered devicedrivers: */\r
40 \r
41         for(t=1,l=firstloader; l!=NULL; l=l->next, t++){\r
42                 printf("%d. %s\n",t,l->version);\r
43         }\r
44 }\r
45 \r
46 \r
47 void ML_RegisterLoader(LOADER *ldr)\r
48 {\r
49         LOADER *l;\r
50 \r
51         if(firstloader==NULL){\r
52                 firstloader=ldr;\r
53                 ldr->next=NULL;\r
54         }\r
55         else{\r
56                 ldr->next=firstloader;\r
57                 firstloader=ldr;\r
58         }\r
59 }\r
60 \r
61 \r
62 \r
63 void *MyMalloc(size_t size)\r
64 /*\r
65         Same as malloc, but sets error variable ml_errno when it failed\r
66 */\r
67 {\r
68         void *d;\r
69 \r
70         d=malloc(size);\r
71         if(d==NULL){\r
72                 myerr="Error allocating structure";\r
73         }\r
74         return d;\r
75 }\r
76 \r
77 \r
78 \r
79 void *MyCalloc(size_t nitems,size_t size)\r
80 /*\r
81         Same as calloc, but sets error variable ml_errno when it failed\r
82 */\r
83 {\r
84         void *d;\r
85 \r
86         d=calloc(nitems,size);\r
87         if(d==NULL){\r
88                 myerr="Error allocating structure";\r
89         }\r
90         return d;\r
91 }\r
92 \r
93 \r
94 \r
95 BOOL ReadComment(UWORD len)\r
96 {\r
97         int t;\r
98 \r
99         if(len){\r
100                 if(!(of.comment=(char *)MyMalloc(len+1))) return 0;\r
101                 fread(of.comment,len,1,modfp);\r
102                 of.comment[len]=0;\r
103 \r
104                 /* strip any control-characters in the comment: */\r
105 \r
106                 for(t=0;t<len;t++){\r
107                         if(of.comment[t]<32) of.comment[t]=' ';\r
108                 }\r
109         }\r
110         return 1;\r
111 }\r
112 \r
113 \r
114 \r
115 BOOL AllocPatterns(void)\r
116 {\r
117         int s,t,tracks=0;\r
118 \r
119         /* Allocate track sequencing array */\r
120 \r
121         if(!(of.patterns=(UWORD *)MyCalloc((ULONG)of.numpat*of.numchn,sizeof(UWORD)))) return 0;\r
122         if(!(of.pattrows=(UWORD *)MyCalloc(of.numpat,sizeof(UWORD)))) return 0;\r
123 \r
124         for(t=0;t<of.numpat;t++){\r
125 \r
126                 of.pattrows[t]=64;\r
127 \r
128                 for(s=0;s<of.numchn;s++){\r
129                         of.patterns[(t*of.numchn)+s]=tracks++;\r
130                 }\r
131         }\r
132 \r
133         return 1;\r
134 }\r
135 \r
136 \r
137 BOOL AllocTracks(void)\r
138 {\r
139         if(!(of.tracks=(UBYTE **)MyCalloc(of.numtrk,sizeof(UBYTE *)))) return 0;\r
140         return 1;\r
141 }\r
142 \r
143 \r
144 \r
145 BOOL AllocInstruments(void)\r
146 {\r
147         UWORD t;\r
148 \r
149         if(!(of.instruments=(INSTRUMENT *)MyCalloc(of.numins,sizeof(INSTRUMENT)))) return 0;\r
150         return 1;\r
151 }\r
152 \r
153 \r
154 BOOL AllocSamples(INSTRUMENT *i)\r
155 {\r
156         UWORD u,n;\r
157 \r
158         if(n=i->numsmp){\r
159                 if(!(i->samples=(SAMPLE *)MyCalloc(n,sizeof(SAMPLE)))) return 0;\r
160 \r
161                 for(u=0; u<n; u++){\r
162                         i->samples[u].panning=128;\r
163                         i->samples[u].handle=-1;\r
164                 }\r
165         }\r
166         return 1;\r
167 }\r
168 \r
169 \r
170 char *DupStr(char *s,UWORD len)\r
171 /*\r
172         Creates a CSTR out of a character buffer of 'len' bytes, but strips\r
173         any terminating non-printing characters like 0, spaces etc.\r
174 */\r
175 {\r
176         UWORD t;\r
177         char *d=NULL;\r
178 \r
179         /* Scan for first printing char in buffer [includes high ascii up to 254] */\r
180 \r
181         while(len){\r
182                 if(!(s[len-1]>=0 && s[len-1]<=0x20)) break;\r
183                 len--;\r
184         }\r
185 \r
186         if(len){\r
187 \r
188                 /* When the buffer wasn't completely empty, allocate\r
189                    a cstring and copy the buffer into that string, except\r
190                    for any control-chars */\r
191 \r
192                 if((d=(char *)malloc(len+1))!=NULL){\r
193                         for(t=0;t<len;t++) {\r
194                                 d[t]=(s[t]>=0 && s[t]<32) ? ' ': s[t];\r
195                         }\r
196                         d[t]=0;\r
197                 }\r
198         }\r
199 \r
200         return d;\r
201 }\r
202 \r
203 \r
204 \r
205 BOOL ML_LoadSamples(void)\r
206 {\r
207         UWORD t,u;\r
208         INSTRUMENT *i;\r
209         SAMPLE *s;\r
210 \r
211         for(t=0;t<of.numins;t++){\r
212 \r
213                 i=&of.instruments[t];\r
214 \r
215                 for(u=0; u<i->numsmp; u++){\r
216 \r
217                         s=&i->samples[u];\r
218 \r
219 /*              printf("Loading Sample %d\n",t); */\r
220 \r
221                 /* sample has to be loaded ? -> increase\r
222                    number of samples and allocate memory and\r
223                    load sample */\r
224 \r
225                         if(s->length){\r
226 \r
227                                 if(s->seekpos){\r
228                                         _mm_fseek(modfp,s->seekpos,SEEK_SET);\r
229                                 }\r
230 \r
231                                 /* Call the sample load routine of the driver module.\r
232                                    It has to return a 'handle' (>=0) that identifies\r
233                                    the sample */\r
234 \r
235                                 s->handle=MD_SampleLoad(modfp,\r
236                                                                                 s->length,\r
237                                                                                 s->loopstart,\r
238                                                                                 s->loopend,\r
239                                                                                 s->flags);\r
240 \r
241                                 if(s->handle<0) return 0;\r
242                         }\r
243                 }\r
244         }\r
245         return 1;\r
246 }\r
247 \r
248 \r
249 BOOL ML_LoadHeader(void)\r
250 {\r
251         BOOL ok=0;\r
252         LOADER *l;\r
253 \r
254         /* Try to find a loader that recognizes the module */\r
255 \r
256         for(l=firstloader; l!=NULL; l=l->next){\r
257                 _mm_rewind(modfp);\r
258                 if(l->Test()) break;\r
259         }\r
260 \r
261         if(l==NULL){\r
262                 myerr="Unknown module format.";\r
263                 return 0;\r
264         }\r
265 \r
266         /* init unitrk routines */\r
267 \r
268         if(!UniInit()) return 0;\r
269 \r
270         /* init module loader */\r
271 \r
272         if(l->Init()){\r
273                 _mm_rewind(modfp);\r
274                  ok=l->Load();\r
275         }\r
276 \r
277         l->Cleanup();\r
278 \r
279         /* free unitrk allocations */\r
280 \r
281         UniCleanup();\r
282         return ok;\r
283 }\r
284 \r
285 \r
286 \r
287 void ML_XFreeInstrument(INSTRUMENT *i)\r
288 {\r
289         UWORD t;\r
290 \r
291         if(i->samples!=NULL){\r
292                 for(t=0; t<i->numsmp; t++){\r
293                         if(i->samples[t].handle>=0){\r
294                                 MD_SampleUnLoad(i->samples[t].handle);\r
295                         }\r
296                 }\r
297                 free(i->samples);\r
298         }\r
299         if(i->insname!=NULL) free(i->insname);\r
300 }\r
301 \r
302 \r
303 void ML_FreeEx(UNIMOD *mf)\r
304 {\r
305         UWORD t;\r
306 \r
307         if(mf->modtype!=NULL) free(mf->modtype);\r
308         if(mf->patterns!=NULL) free(mf->patterns);\r
309         if(mf->pattrows!=NULL) free(mf->pattrows);\r
310 \r
311         if(mf->tracks!=NULL){\r
312                 for(t=0;t<mf->numtrk;t++){\r
313                         if(mf->tracks[t]!=NULL) free(mf->tracks[t]);\r
314                 }\r
315                 free(mf->tracks);\r
316         }\r
317 \r
318         if(mf->instruments!=NULL){\r
319                 for(t=0;t<mf->numins;t++){\r
320                         ML_XFreeInstrument(&mf->instruments[t]);\r
321                 }\r
322                 free(mf->instruments);\r
323         }\r
324 \r
325         if(mf->songname!=NULL) free(mf->songname);\r
326         if(mf->comment!=NULL) free(mf->comment);\r
327 }\r
328 \r
329 \r
330 \r
331 /******************************************\r
332 \r
333         Next are the user-callable functions\r
334 \r
335 ******************************************/\r
336 \r
337 \r
338 void ML_Free(UNIMOD *mf)\r
339 {\r
340         if(mf!=NULL){\r
341                 ML_FreeEx(mf);\r
342                 free(mf);\r
343         }\r
344 }\r
345 \r
346 \r
347 \r
348 \r
349 UNIMOD *ML_LoadFP(FILE *fp)\r
350 {\r
351         int t;\r
352         UNIMOD *mf;\r
353 \r
354         /* init fileptr, clear errorcode, clear static modfile: */\r
355 \r
356         modfp=fp;\r
357         myerr=NULL;\r
358         memset(&of,0,sizeof(UNIMOD));\r
359 \r
360         /* init panning array */\r
361 \r
362         for(t=0;t<32;t++){\r
363                 of.panning[t]=((t+1)&2)?255:0;\r
364         }\r
365 \r
366         if(!ML_LoadHeader()){\r
367                 ML_FreeEx(&of);\r
368                 return NULL;\r
369         }\r
370 \r
371         if(!ML_LoadSamples()){\r
372                 ML_FreeEx(&of);\r
373                 return NULL;\r
374         }\r
375 \r
376         if(!(mf=(UNIMOD *)MyCalloc(1,sizeof(UNIMOD)))){\r
377                 ML_FreeEx(&of);\r
378                 return NULL;\r
379         }\r
380 \r
381         /* Copy the static UNIMOD contents\r
382         into the dynamic UNIMOD struct */\r
383 \r
384         memcpy(mf,&of,sizeof(UNIMOD));\r
385 \r
386         return mf;\r
387 }\r
388 \r
389 \r
390 \r
391 UNIMOD *ML_LoadFN(char *filename)\r
392 {\r
393         FILE *fp;\r
394         UNIMOD *mf;\r
395 \r
396         if((fp=fopen(filename,"rb"))==NULL){\r
397                 myerr="Error opening file";\r
398                 return NULL;\r
399         }\r
400 \r
401         mf=ML_LoadFP(fp);\r
402         fclose(fp);\r
403 \r
404         return mf;\r
405 }\r
406 \r