Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison 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 |
comparison
equal
deleted
inserted
replaced
3:71e20a32bd84 | 4:5d614bcc4287 |
---|---|
1 /* | |
2 | |
3 Name: LOAD_MOD.C | |
4 | |
5 Description: | |
6 Generic MOD loader (Protracker, StarTracker, FastTracker, etc) | |
7 | |
8 Portability: | |
9 All systems - all compilers (hopefully) | |
10 | |
11 If this module is found to not be portable to any particular platform, | |
12 please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for | |
13 more information on contacting the author). | |
14 | |
15 */ | |
16 | |
17 #include <string.h> | |
18 #include "mikmod.h" | |
19 | |
20 /************************************************************************* | |
21 *************************************************************************/ | |
22 | |
23 | |
24 typedef struct MSAMPINFO // sample header as it appears in a module | |
25 { CHAR samplename[22]; | |
26 UWORD length; | |
27 UBYTE finetune; | |
28 UBYTE volume; | |
29 UWORD reppos; | |
30 UWORD replen; | |
31 } MSAMPINFO; | |
32 | |
33 | |
34 typedef struct MODULEHEADER // verbatim module header | |
35 { CHAR songname[20]; // the songname.. | |
36 MSAMPINFO samples[31]; // all sampleinfo | |
37 UBYTE songlength; // number of patterns used | |
38 UBYTE magic1; // should be 127 | |
39 UBYTE positions[128]; // which pattern to play at pos | |
40 UBYTE magic2[4]; // string "M.K." or "FLT4" or "FLT8" | |
41 } MODULEHEADER; | |
42 | |
43 #define MODULEHEADERSIZE 1084 | |
44 | |
45 | |
46 typedef struct MODTYPE // struct to identify type of module | |
47 { CHAR id[5]; | |
48 UBYTE channels; | |
49 CHAR *name; | |
50 } MODTYPE; | |
51 | |
52 | |
53 typedef struct MODNOTE | |
54 { UBYTE a,b,c,d; | |
55 } MODNOTE; | |
56 | |
57 | |
58 /************************************************************************* | |
59 *************************************************************************/ | |
60 | |
61 | |
62 CHAR protracker[] = "Protracker"; | |
63 CHAR startracker[] = "Startracker"; | |
64 CHAR fasttracker[] = "Fasttracker"; | |
65 CHAR ins15tracker[] = "15-instrument"; | |
66 CHAR oktalyzer[] = "Oktalyzer"; | |
67 CHAR taketracker[] = "TakeTracker"; | |
68 | |
69 | |
70 MODTYPE modtypes[] = | |
71 { "M.K.",4,protracker, // protracker 4 channel | |
72 "M!K!",4,protracker, // protracker 4 channel | |
73 "FLT4",4,startracker, // startracker 4 channel | |
74 "2CHN",2,fasttracker, // fasttracker 2 channel | |
75 "4CHN",4,fasttracker, // fasttracker 4 channel | |
76 "6CHN",6,fasttracker, // fasttracker 6 channel | |
77 "8CHN",8,fasttracker, // fasttracker 8 channel | |
78 "10CH",10,fasttracker, // fasttracker 10 channel | |
79 "12CH",12,fasttracker, // fasttracker 12 channel | |
80 "14CH",14,fasttracker, // fasttracker 14 channel | |
81 "16CH",16,fasttracker, // fasttracker 16 channel | |
82 "18CH",18,fasttracker, // fasttracker 18 channel | |
83 "20CH",20,fasttracker, // fasttracker 20 channel | |
84 "22CH",22,fasttracker, // fasttracker 22 channel | |
85 "24CH",24,fasttracker, // fasttracker 24 channel | |
86 "26CH",26,fasttracker, // fasttracker 26 channel | |
87 "28CH",28,fasttracker, // fasttracker 28 channel | |
88 "30CH",30,fasttracker, // fasttracker 30 channel | |
89 "32CH",32,fasttracker, // fasttracker 32 channel | |
90 "CD81",8,oktalyzer, // atari oktalyzer 8 channel | |
91 "OKTA",8,oktalyzer, // atari oktalyzer 8 channel | |
92 "16CN",16,taketracker, // taketracker 16 channel | |
93 "32CN",32,taketracker, // taketracker 32 channel | |
94 " ",4,ins15tracker // 15-instrument 4 channel | |
95 }; | |
96 | |
97 static MODULEHEADER *mh = NULL; // raw as-is module header | |
98 static MODNOTE *patbuf = NULL; | |
99 static int modtype = 0; | |
100 | |
101 BOOL MOD_Test(void) | |
102 { | |
103 UBYTE id[4]; | |
104 | |
105 _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET); | |
106 if(!fread(id,4,1,modfp)) return 0; | |
107 | |
108 // find out which ID string | |
109 | |
110 for(modtype=0; modtype<23; modtype++) | |
111 if(!memcmp(id,modtypes[modtype].id,4)) return 1; | |
112 | |
113 return 0; | |
114 } | |
115 | |
116 | |
117 BOOL MOD_Init(void) | |
118 { | |
119 if(!(mh=(MODULEHEADER *)_mm_calloc(1,sizeof(MODULEHEADER)))) return 0; | |
120 return 1; | |
121 } | |
122 | |
123 | |
124 void MOD_Cleanup(void) | |
125 { | |
126 if(mh!=NULL) free(mh); | |
127 if(patbuf!=NULL) free(patbuf); | |
128 | |
129 mh = NULL; | |
130 patbuf = NULL; | |
131 } | |
132 | |
133 | |
134 /* | |
135 Old (amiga) noteinfo: | |
136 | |
137 _____byte 1_____ byte2_ _____byte 3_____ byte4_ | |
138 / \ / \ / \ / \ | |
139 0000 0000-00000000 0000 0000-00000000 | |
140 | |
141 Upper four 12 bits for Lower four Effect command. | |
142 bits of sam- note period. bits of sam- | |
143 ple number. ple number. | |
144 | |
145 */ | |
146 | |
147 | |
148 void ConvertNote(MODNOTE *n) | |
149 { | |
150 UBYTE instrument,effect,effdat,note; | |
151 UWORD period; | |
152 | |
153 // extract the various information from the 4 bytes that | |
154 // make up a single note | |
155 | |
156 instrument = (n->a&0x10)|(n->c>>4); | |
157 period = (((UWORD)n->a&0xf)<<8)+n->b; | |
158 effect = n->c&0xf; | |
159 effdat = n->d; | |
160 | |
161 // Convert the period to a note number | |
162 | |
163 note=0; | |
164 if(period!=0) | |
165 { for(note=0; note<60; note++) | |
166 if(period >= npertab[note]) break; | |
167 note++; | |
168 if(note==61) note = 0; | |
169 } | |
170 | |
171 if(instrument!=0) UniInstrument(instrument-1); | |
172 if(note!=0) UniNote(note+23); | |
173 | |
174 // Convert pattern jump from Dec to Hex | |
175 if(effect == 0xd) | |
176 effdat = (((effdat&0xf0)>>4)*10)+(effdat&0xf); | |
177 | |
178 UniPTEffect(effect,effdat); | |
179 } | |
180 | |
181 | |
182 UBYTE *ConvertTrack(MODNOTE *n) | |
183 { | |
184 int t; | |
185 | |
186 UniReset(); | |
187 for(t=0;t<64;t++) | |
188 { ConvertNote(n); | |
189 UniNewline(); | |
190 n+=of.numchn; | |
191 } | |
192 return UniDup(); | |
193 } | |
194 | |
195 | |
196 BOOL ML_LoadPatterns(void) | |
197 // Loads all patterns of a modfile and converts them into the | |
198 // 3 byte format. | |
199 { | |
200 int t,s,tracks = 0; | |
201 | |
202 if(!AllocPatterns()) return 0; | |
203 if(!AllocTracks()) return 0; | |
204 | |
205 // Allocate temporary buffer for loading | |
206 // and converting the patterns | |
207 | |
208 if(!(patbuf=(MODNOTE *)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0; | |
209 | |
210 for(t=0; t<of.numpat; t++) | |
211 { // Load the pattern into the temp buffer | |
212 // and convert it | |
213 | |
214 for(s=0; s<(64U*of.numchn); s++) | |
215 { patbuf[s].a = _mm_read_UBYTE(modfp); | |
216 patbuf[s].b = _mm_read_UBYTE(modfp); | |
217 patbuf[s].c = _mm_read_UBYTE(modfp); | |
218 patbuf[s].d = _mm_read_UBYTE(modfp); | |
219 } | |
220 | |
221 for(s=0; s<of.numchn; s++) | |
222 if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0; | |
223 } | |
224 | |
225 return 1; | |
226 } | |
227 | |
228 | |
229 BOOL MOD_Load(void) | |
230 { | |
231 int t; | |
232 SAMPLE *q; | |
233 MSAMPINFO *s; // old module sampleinfo | |
234 | |
235 // try to read module header | |
236 | |
237 _mm_read_string((CHAR *)mh->songname,20,modfp); | |
238 | |
239 for(t=0; t<31; t++) | |
240 { s = &mh->samples[t]; | |
241 _mm_read_string(s->samplename,22,modfp); | |
242 s->length =_mm_read_M_UWORD(modfp); | |
243 s->finetune =_mm_read_UBYTE(modfp); | |
244 s->volume =_mm_read_UBYTE(modfp); | |
245 s->reppos =_mm_read_M_UWORD(modfp); | |
246 s->replen =_mm_read_M_UWORD(modfp); | |
247 } | |
248 | |
249 mh->songlength =_mm_read_UBYTE(modfp); | |
250 mh->magic1 =_mm_read_UBYTE(modfp); | |
251 | |
252 _mm_read_UBYTES(mh->positions,128,modfp); | |
253 _mm_read_UBYTES(mh->magic2,4,modfp); | |
254 | |
255 if(feof(modfp)) | |
256 { _mm_errno = MMERR_LOADING_HEADER; | |
257 return 0; | |
258 } | |
259 | |
260 // set module variables | |
261 | |
262 of.initspeed = 6; | |
263 of.inittempo = 125; | |
264 of.numchn = modtypes[modtype].channels; // get number of channels | |
265 of.modtype = strdup(modtypes[modtype].name); // get ascii type of mod | |
266 of.songname = DupStr(mh->songname,20); // make a cstr of songname | |
267 of.numpos = mh->songlength; // copy the songlength | |
268 | |
269 if(!AllocPositions(of.numpos)) return 0; | |
270 for(t=0; t<of.numpos; t++) | |
271 of.positions[t] = mh->positions[t]; | |
272 | |
273 // Count the number of patterns | |
274 | |
275 of.numpat = 0; | |
276 | |
277 for(t=0; t<of.numpos; t++) | |
278 { if(of.positions[t] > of.numpat) | |
279 of.numpat = of.positions[t]; | |
280 } | |
281 of.numpat++; | |
282 of.numtrk = of.numpat*of.numchn; | |
283 | |
284 // Finally, init the sampleinfo structures | |
285 of.numins = of.numsmp = 31; | |
286 | |
287 if(!AllocSamples()) return 0; | |
288 | |
289 s = mh->samples; // init source pointer | |
290 q = of.samples; | |
291 | |
292 for(t=0; t<of.numins; t++) | |
293 { // convert the samplename | |
294 q->samplename = DupStr(s->samplename, 22); | |
295 | |
296 // init the sampleinfo variables and | |
297 // convert the size pointers to longword format | |
298 | |
299 q->speed = finetune[s->finetune & 0xf]; | |
300 q->volume = s->volume; | |
301 q->loopstart = (ULONG)s->reppos << 1; | |
302 q->loopend = q->loopstart + ((ULONG)s->replen << 1); | |
303 q->length = (ULONG)s->length << 1; | |
304 | |
305 q->flags = SF_SIGNED; | |
306 if(s->replen > 1) q->flags |= SF_LOOP; | |
307 | |
308 // fix replen if repend > length | |
309 if(q->loopend > q->length) q->loopend = q->length; | |
310 | |
311 s++; // point to next source sampleinfo | |
312 q++; | |
313 } | |
314 | |
315 if(!ML_LoadPatterns()) return 0; | |
316 return 1; | |
317 } | |
318 | |
319 | |
320 CHAR *MOD_LoadTitle(void) | |
321 { | |
322 CHAR s[20]; | |
323 | |
324 _mm_fseek(modfp,0,SEEK_SET); | |
325 if(!fread(s,20,1,modfp)) return NULL; | |
326 | |
327 return(DupStr(s,20)); | |
328 } | |
329 | |
330 | |
331 MLOADER load_mod = | |
332 { NULL, | |
333 "Standard module", | |
334 "Portable MOD loader v0.11", | |
335 MOD_Init, | |
336 MOD_Test, | |
337 MOD_Load, | |
338 MOD_Cleanup, | |
339 MOD_LoadTitle | |
340 }; | |
341 |