added an old version of mikmod for dos
[dosdemo] / libs / oldmik / src / load_m15.c
1 /*
2
3 Name:
4 LOAD_M15.C
5
6 Description:
7 15 instrument MOD loader
8
9 Portability:
10 All systems - all compilers (hopefully)
11
12 */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include "mikmod.h"
18
19 /*************************************************************************
20 *************************************************************************/
21
22
23 typedef struct MSAMPINFO{       /* sample header as it appears in a module */
24         char  samplename[22];
25         UWORD length;
26         UBYTE finetune;
27         UBYTE volume;
28         UWORD reppos;
29         UWORD replen;
30 } MSAMPINFO;
31
32
33 typedef struct MODULEHEADER{                 /* verbatim module header */
34         char       songname[20];                /* the songname.. */
35         MSAMPINFO  samples[15];                         /* all sampleinfo */
36         UBYTE      songlength;                          /* number of patterns used */
37         UBYTE      magic1;                                      /* should be 127 */
38         UBYTE      positions[128];                      /* which pattern to play at pos */
39 } MODULEHEADER;
40
41
42 typedef struct MODNOTE{
43         UBYTE a,b,c,d;
44 } MODNOTE;
45
46
47 /*************************************************************************
48 *************************************************************************/
49
50 static MODULEHEADER *mh;        /* raw as-is module header */
51 static MODNOTE *patbuf;
52
53
54 static BOOL LoadModuleHeader(MODULEHEADER *mh)
55 {
56         int t;
57
58         _mm_read_str(mh->songname,20,modfp);
59
60         for(t=0;t<15;t++){
61                 MSAMPINFO *s= &mh->samples[t];
62                 _mm_read_str(s->samplename,22,modfp);
63                 s->length       =_mm_read_M_UWORD(modfp);
64                 s->finetune     =_mm_read_UBYTE(modfp);
65                 s->volume       =_mm_read_UBYTE(modfp);
66                 s->reppos       =_mm_read_M_UWORD(modfp);
67                 s->replen       =_mm_read_M_UWORD(modfp);
68         }
69
70         mh->songlength  =_mm_read_UBYTE(modfp);
71         mh->magic1              =_mm_read_UBYTE(modfp);                                      /* should be 127 */
72         _mm_read_UBYTES(mh->positions,128,modfp);
73
74         return(!feof(modfp));
75 }
76
77
78
79 BOOL M15_Test(void)
80 {
81         int t;
82         MODULEHEADER mh;
83
84         if(!LoadModuleHeader(&mh)) return 0;
85
86         for(t=0;t<15;t++){
87
88                 /* all finetunes should be zero */
89                 if(mh.samples[t].finetune!=0) return 0;
90
91                 /* all volumes should be <=64 */
92                 if(mh.samples[t].volume>64) return 0;
93         }
94         if(mh.magic1>127) return 0;    /* and magic1 should be <128 */
95
96         return 1;
97 }
98
99
100 BOOL M15_Init(void)
101 {
102         patbuf=NULL;
103         if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
104         return 1;
105 }
106
107
108 void M15_Cleanup(void)
109 {
110         if(mh!=NULL) free(mh);
111         if(patbuf!=NULL) free(patbuf);
112 }
113
114
115 /*
116
117 Old (amiga) noteinfo:
118
119  _____byte 1_____   byte2_    _____byte 3_____   byte4_
120 /                \ /      \  /                \ /      \
121 0000          0000-00000000  0000          0000-00000000
122
123 Upper four    12 bits for    Lower four    Effect command.
124 bits of sam-  note period.   bits of sam-
125 ple number.                  ple number.
126
127
128 */
129
130
131 UWORD M15_npertab[60]={
132
133 /* -> Tuning 0 */
134
135         1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
136         856,808,762,720,678,640,604,570,538,508,480,453,
137         428,404,381,360,339,320,302,285,269,254,240,226,
138         214,202,190,180,170,160,151,143,135,127,120,113,
139         107,101,95,90,85,80,75,71,67,63,60,56
140 };
141
142
143 void M15_ConvertNote(MODNOTE *n)
144 {
145         UBYTE instrument,effect,effdat,note;
146         UWORD period;
147
148         /* extract the various information from the 4 bytes that
149            make up a single note */
150
151         instrument=(n->a&0x10)|(n->c>>4);
152         period=(((UWORD)n->a&0xf)<<8)+n->b;
153         effect=n->c&0xf;
154         effdat=n->d;
155
156         /* Convert the period to a note number */
157
158         note=0;
159         if(period!=0){
160                 for(note=0;note<60;note++){
161                         if(period>=M15_npertab[note]) break;
162                 }
163                 note++;
164                 if(note==61) note=0;
165         }
166
167         if(instrument!=0){
168                 UniInstrument(instrument-1);
169         }
170
171         if(note!=0){
172                 UniNote(note+23);
173         }
174
175         UniPTEffect(effect,effdat);
176 }
177
178
179
180 UBYTE *M15_ConvertTrack(MODNOTE *n)
181 {
182         int t;
183
184         UniReset();
185         for(t=0;t<64;t++){
186                 M15_ConvertNote(n);
187                 UniNewline();
188                 n+=of.numchn;
189         }
190         return UniDup();
191 }
192
193
194
195 BOOL M15_LoadPatterns(void)
196 /*
197         Loads all patterns of a modfile and converts them into the
198         3 byte format.
199 */
200 {
201         int t,s,tracks=0;
202
203         if(!AllocPatterns()) return 0;
204         if(!AllocTracks()) return 0;
205
206         /* Allocate temporary buffer for loading
207            and converting the patterns */
208
209         if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
210
211         for(t=0;t<of.numpat;t++){
212
213                 /* Load the pattern into the temp buffer
214                    and convert it */
215
216                 for(s=0;s<(64U*of.numchn);s++){
217                         patbuf[s].a=_mm_read_UBYTE(modfp);
218                         patbuf[s].b=_mm_read_UBYTE(modfp);
219                         patbuf[s].c=_mm_read_UBYTE(modfp);
220                         patbuf[s].d=_mm_read_UBYTE(modfp);
221                 }
222
223                 for(s=0;s<of.numchn;s++){
224                         if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
225                 }
226         }
227
228         return 1;
229 }
230
231
232
233 BOOL M15_Load(void)
234 {
235         int t;
236         INSTRUMENT *d;          /* new sampleinfo structure */
237         SAMPLE *q;
238         MSAMPINFO *s;           /* old module sampleinfo */
239
240         /* try to read module header */
241
242         if(!LoadModuleHeader(mh)){
243                 myerr=ERROR_LOADING_HEADER;
244                 return 0;
245         }
246
247         /* set module variables */
248
249         of.initspeed=6;
250         of.inittempo=125;
251         of.numchn=4;                                                    /* get number of channels */
252         of.modtype=strdup("15-instrument");             /* get ascii type of mod */
253         of.songname=DupStr(mh->songname,20);        /* make a cstr of songname */
254         of.numpos=mh->songlength;                       /* copy the songlength */
255         memcpy(of.positions,mh->positions,128);     /* copy the position array */
256
257         /* Count the number of patterns */
258
259         of.numpat=0;
260
261         for(t=0;t<128;t++){             /* <-- BUGFIX... have to check ALL positions */
262                 if(of.positions[t] > of.numpat){
263                         of.numpat=of.positions[t];
264                 }
265         }
266         of.numpat++;
267         of.numtrk=of.numpat*of.numchn;
268
269         /* Finally, init the sampleinfo structures */
270
271         of.numins=15;
272         if(!AllocInstruments()) return 0;
273
274         s=mh->samples;          /* init source pointer */
275         d=of.instruments;       /* init dest pointer */
276
277         for(t=0;t<of.numins;t++){
278
279                 d->numsmp=1;
280                 if(!AllocSamples(d)) return 0;
281
282                 q=d->samples;
283
284                 /* convert the samplename */
285
286                 d->insname=DupStr(s->samplename,22);
287
288                 /* init the sampleinfo variables and
289                    convert the size pointers to longword format */
290
291                 q->c2spd=finetune[s->finetune&0xf];
292                 q->volume=s->volume;
293                 q->loopstart=s->reppos;
294                 q->loopend=q->loopstart+(s->replen<<1);
295                 q->length=s->length<<1;
296                 q->seekpos=0;
297
298                 q->flags=SF_SIGNED;
299                 if(s->replen>1) q->flags|=SF_LOOP;
300
301                 /* fix replen if repend>length */
302
303                 if(q->loopend>q->length) q->loopend=q->length;
304
305                 s++;    /* point to next source sampleinfo */
306                 d++;    /* point to next destiny sampleinfo */
307         }
308
309         if(!M15_LoadPatterns()) return 0;
310         return 1;
311 }
312
313
314
315 LOADER load_m15={
316         NULL,
317         "15-instrument module",
318         "Portable MOD-15 loader v0.1",
319         M15_Init,
320         M15_Test,
321         M15_Load,
322         M15_Cleanup
323 };