Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/load_it.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_IT.C | |
4 | |
5 Description: | |
6 ImpulseTracker (IT) module loader | |
7 | |
8 Portability: | |
9 All systems - all compilers (hopefully) | |
10 | |
11 Copyright 1997 by Jake Stine and Divine Entertainment | |
12 | |
13 If this module is found to not be portable to any particular platform, | |
14 please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for | |
15 more information on contacting the author). | |
16 */ | |
17 | |
18 #include <string.h> | |
19 #include "mikmod.h" | |
20 | |
21 /************************************************************************** | |
22 **************************************************************************/ | |
23 | |
24 typedef struct ITNOTE | |
25 { UBYTE note,ins,volpan,cmd,inf; | |
26 } ITNOTE; | |
27 | |
28 UBYTE *IT_ConvertTrack(ITNOTE *tr,UWORD numrows); | |
29 | |
30 | |
31 // Raw IT header struct: | |
32 | |
33 typedef struct ITHEADER | |
34 { CHAR songname[26]; | |
35 UBYTE blank01[2]; | |
36 UWORD ordnum; | |
37 UWORD insnum; | |
38 UWORD smpnum; | |
39 UWORD patnum; | |
40 UWORD cwt; // Created with tracker (y.xx = 0x0yxx) | |
41 UWORD cmwt; // Compatable with tracker ver > than val. | |
42 UWORD flags; | |
43 UWORD special; // bit 0 set = song message attached | |
44 UBYTE globvol; | |
45 UBYTE mixvol; // mixing volume [ignored] | |
46 UBYTE initspeed; | |
47 UBYTE inittempo; | |
48 UBYTE pansep; // panning separation between channels | |
49 UBYTE zerobyte; | |
50 UWORD msglength; | |
51 ULONG msgoffset; | |
52 UBYTE blank02[4]; | |
53 | |
54 UBYTE pantable[64]; | |
55 UBYTE voltable[64]; | |
56 } ITHEADER; | |
57 | |
58 | |
59 // Raw IT sampleinfo struct: | |
60 | |
61 typedef struct ITSAMPLE | |
62 { CHAR filename[12]; | |
63 UBYTE zerobyte; | |
64 UBYTE globvol; | |
65 UBYTE flag; | |
66 UBYTE volume; | |
67 UBYTE panning; | |
68 CHAR sampname[28]; | |
69 UWORD convert; // sample conversion flag | |
70 ULONG length; | |
71 ULONG loopbeg; | |
72 ULONG loopend; | |
73 ULONG c5spd; | |
74 ULONG susbegin; | |
75 ULONG susend; | |
76 ULONG sampoffset; | |
77 UBYTE vibspeed; | |
78 UBYTE vibdepth; | |
79 UBYTE vibrate; | |
80 UBYTE vibwave; // 0 = sine; 1 = rampdown; 2 = square; 3 = random (speed ignored) | |
81 | |
82 UBYTE noteindex; // for converting c5spd to finetune | |
83 } ITSAMPLE; | |
84 | |
85 | |
86 typedef struct ITINSTHEADER | |
87 { ULONG size; // (dword) Instrument size | |
88 CHAR filename[12]; // (char) Instrument filename | |
89 UBYTE zerobyte; // (byte) Instrument type (always 0) | |
90 UBYTE volflg; | |
91 UBYTE volpts; | |
92 UBYTE volbeg; // (byte) Volume loop start (node) | |
93 UBYTE volend; // (byte) Volume loop end (node) | |
94 UBYTE volsusbeg; // (byte) Volume sustain begin (node) | |
95 UBYTE volsusend; // (byte) Volume Sustain end (node) | |
96 UBYTE panflg; | |
97 UBYTE panpts; | |
98 UBYTE panbeg; // (byte) channel loop start (node) | |
99 UBYTE panend; // (byte) channel loop end (node) | |
100 UBYTE pansusbeg; // (byte) cahnnel sustain begin (node) | |
101 UBYTE pansusend; // (byte) channel Sustain end (node) | |
102 UBYTE pitflg; | |
103 UBYTE pitpts; | |
104 UBYTE pitbeg; // (byte) pitch loop start (node) | |
105 UBYTE pitend; // (byte) pitch loop end (node) | |
106 UBYTE pitsusbeg; // (byte) pitch sustain begin (node) | |
107 UBYTE pitsusend; // (byte) pitch Sustain end (node) | |
108 UWORD blank; | |
109 UBYTE globvol; | |
110 UBYTE chanpan; | |
111 UWORD fadeout; // Envelope end / NNA volume fadeout | |
112 UBYTE dnc; // Duplicate note check | |
113 UBYTE dca; // Duplicate check action | |
114 UBYTE dct; // Duplicate check type | |
115 UBYTE nna; // New Note Action [0,1,2,3] | |
116 UWORD trkvers; // tracker version used to save [in files only] | |
117 UBYTE ppsep; // Pitch-pan Separation | |
118 UBYTE ppcenter; // Pitch-pan Center | |
119 UBYTE rvolvar; // random volume varations | |
120 UBYTE rpanvar; // random panning varations | |
121 UWORD numsmp; // Number of samples in instrument [in files only] | |
122 CHAR name[26]; // Instrument name | |
123 UBYTE blank01[6]; | |
124 UWORD samptable[120]; // sample for each note [note / samp pairs] | |
125 | |
126 UBYTE volenv[200]; // volume envelope (IT 1.x stuff) | |
127 UBYTE oldvoltick[25]; // volume tick position (IT 1.x stuff) | |
128 UBYTE volnode[25]; // aplitude of volume nodes | |
129 UWORD voltick[25]; // tick value of volume nodes | |
130 SBYTE pannode[25]; // panenv - node points | |
131 UWORD pantick[25]; // tick value of panning nodes | |
132 SBYTE pitnode[25]; // pitchenv - node points | |
133 UWORD pittick[25]; // tick value of pitch nodes | |
134 } ITINSTHEADER; | |
135 | |
136 | |
137 /************************************************************************** | |
138 **************************************************************************/ | |
139 | |
140 extern SBYTE remap[64]; // for removing empty channels | |
141 extern UBYTE *poslookup; // S3M/IT fix - removing blank patterns needs a | |
142 // lookup table to fix position-jump commands | |
143 static ULONG *paraptr = NULL; // parapointer array (see IT docs) | |
144 static ITHEADER *mh = NULL; | |
145 static ITNOTE *itpat = NULL; // allocate to space for one full pattern | |
146 static UBYTE *mask = NULL; // arrays allocated to 64 elements and used for | |
147 static ITNOTE *last = NULL; // uncompressing IT's pattern information | |
148 static int numtrk = 0; | |
149 static int old_effect; // if set, use S3M old-effects stuffs | |
150 static int *noteindex; | |
151 | |
152 CHAR IT_Version[] = "ImpulseTracker x.xx"; | |
153 | |
154 | |
155 BOOL IT_Test(void) | |
156 { | |
157 UBYTE id[4]; | |
158 | |
159 if(!_mm_read_UBYTES(id,4,modfp)) return 0; | |
160 if(!memcmp(id,"IMPM",4)) return 1; | |
161 return 0; | |
162 } | |
163 | |
164 BOOL IT_Init(void) | |
165 { | |
166 if((mh=(ITHEADER *)_mm_calloc(1,sizeof(ITHEADER)))==NULL) return 0; | |
167 if((poslookup=(UBYTE *)_mm_malloc(256*sizeof(UBYTE)))==NULL) return 0; | |
168 if((itpat=(ITNOTE *)_mm_malloc(200*64*sizeof(ITNOTE)))==NULL) return 0; | |
169 if((mask=(UBYTE *)_mm_malloc(64*sizeof(UBYTE)))==NULL) return 0; | |
170 if((last=(ITNOTE *)_mm_malloc(64*sizeof(ITNOTE)))==NULL) return 0; | |
171 | |
172 return 1; | |
173 } | |
174 | |
175 void IT_Cleanup(void) | |
176 { | |
177 if(mh!=NULL) free(mh); | |
178 if(poslookup!=NULL) free(poslookup); | |
179 if(itpat!=NULL) free(itpat); | |
180 if(mask!=NULL) free(mask); | |
181 if(last!=NULL) free(last); | |
182 if(paraptr!=NULL) free(paraptr); | |
183 if(noteindex!=NULL) free(noteindex); | |
184 | |
185 mh = NULL; | |
186 poslookup = NULL; | |
187 itpat = NULL; | |
188 mask = NULL; | |
189 last = NULL; | |
190 paraptr = NULL; | |
191 noteindex = NULL; | |
192 } | |
193 | |
194 | |
195 BOOL IT_GetNumChannels(UWORD patrows) | |
196 | |
197 // Because so many IT files have 64 channels as the set number used, but really | |
198 // only use far less (usually 8 to 12 still), I had to make this function, | |
199 // which determines the number of channels that are actually USED by a pattern. | |
200 // | |
201 // For every channel that's used, it sets the appropriate array entry of the | |
202 // global varialbe 'isused' | |
203 // | |
204 // NOTE: You must first seek to the file location of the pattern before calling | |
205 // this procedure. | |
206 // Returns 1 on error | |
207 { | |
208 int row=0,flag,ch; | |
209 | |
210 do | |
211 { flag = _mm_read_UBYTE(modfp); | |
212 if(flag == EOF) | |
213 { _mm_errno = MMERR_LOADING_PATTERN; | |
214 return 1; | |
215 } | |
216 | |
217 if(flag == 0) | |
218 { row++; | |
219 } else | |
220 { ch = (flag-1) & 63; | |
221 remap[ch] = 0; | |
222 if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp); | |
223 if(mask[ch] & 1) _mm_read_UBYTE(modfp); | |
224 if(mask[ch] & 2) _mm_read_UBYTE(modfp); | |
225 if(mask[ch] & 4) _mm_read_UBYTE(modfp); | |
226 if(mask[ch] & 8) { _mm_read_UBYTE(modfp); _mm_read_UBYTE(modfp); } | |
227 } | |
228 } while(row < patrows); | |
229 | |
230 return 0; | |
231 } | |
232 | |
233 | |
234 BOOL IT_ReadPattern(UWORD patrows) | |
235 { | |
236 int blah; | |
237 int row=0,flag,ch; | |
238 ITNOTE *itt = itpat, dummy,*n,*l; | |
239 | |
240 memset(itt,255,patrows*of.numchn*sizeof(ITNOTE)); | |
241 | |
242 do | |
243 { flag = _mm_read_UBYTE(modfp); | |
244 if(feof(modfp)) | |
245 { _mm_errno = MMERR_LOADING_PATTERN; | |
246 return 0; | |
247 } | |
248 if(flag == 0) | |
249 { itt = &itt[of.numchn]; | |
250 row++; | |
251 } else | |
252 { ch = remap[(flag-1) & 63]; | |
253 if(ch != -1) | |
254 { n = &itt[ch]; | |
255 l = &last[ch]; | |
256 } else | |
257 { n = l = &dummy; } | |
258 | |
259 if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp); | |
260 if(mask[ch] & 1) if((l->note = n->note = _mm_read_UBYTE(modfp)) == 255) | |
261 { l->note = n->note = 253; } | |
262 if(mask[ch] & 2) l->ins = n->ins = _mm_read_UBYTE(modfp); | |
263 if(mask[ch] & 4) l->volpan = n->volpan = _mm_read_UBYTE(modfp); | |
264 if(mask[ch] & 8) { l->cmd = n->cmd = _mm_read_UBYTE(modfp); | |
265 l->inf = n->inf = _mm_read_UBYTE(modfp); } | |
266 if(mask[ch] & 16) n->note = l->note; | |
267 if(mask[ch] & 32) n->ins = l->ins; | |
268 if(mask[ch] & 64) n->volpan = l->volpan; | |
269 if(mask[ch] & 128) { n->cmd = l->cmd; | |
270 n->inf = l->inf; } | |
271 } | |
272 } while(row < patrows); | |
273 | |
274 for(blah=0; blah<of.numchn; blah++) | |
275 of.tracks[numtrk++] = IT_ConvertTrack(&itpat[blah],patrows); | |
276 | |
277 return 1; | |
278 } | |
279 | |
280 | |
281 void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, BOOL oldeffect); | |
282 | |
283 // table for porta-to-note command within volume/panning column | |
284 static UBYTE portatable[] = "1, 4, 8, 16, 32, 64, 96, 128, 255"; | |
285 | |
286 UBYTE *IT_ConvertTrack(ITNOTE *tr, UWORD numrows) | |
287 { | |
288 int t; | |
289 | |
290 UBYTE note,ins,volpan; | |
291 | |
292 UniReset(); | |
293 | |
294 for(t=0; t<numrows; t++) | |
295 { note = tr[t*of.numchn].note; | |
296 ins = tr[t*of.numchn].ins; | |
297 volpan = tr[t*of.numchn].volpan; | |
298 | |
299 if(note!=255) | |
300 { if(note==253) | |
301 UniWrite(UNI_KEYOFF); | |
302 else if(note==254) | |
303 UniPTEffect(0xc,0); // <- note cut command | |
304 else | |
305 UniNote(note); | |
306 } | |
307 | |
308 if((ins != 0) && (ins < 100)) UniInstrument(ins-1); | |
309 | |
310 // process volume / panning column | |
311 // volume / panning effects do NOT all share the same memory address | |
312 // yet. That requires more work than I care to apply at the moment ;) | |
313 | |
314 if(volpan<=64) | |
315 { UniVolEffect(VOL_VOLUME,volpan); | |
316 } else if((volpan>=65) && (volpan<=74)) // fine volume slide up (65-74) | |
317 { UniVolEffect(VOL_VOLSLIDE,0x0f + ((volpan-65)<<4)); | |
318 } else if((volpan>=75) && (volpan<=84)) // fine volume slide down (75-84) | |
319 { UniVolEffect(VOL_VOLSLIDE,0xf0 + (volpan-75)); | |
320 } else if((volpan>=85) && (volpan<=94)) // volume slide up (85-94) | |
321 { UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4)); | |
322 } else if((volpan>=95) && (volpan<=104)) // volume slide down (95-104) | |
323 { UniVolEffect(VOL_VOLSLIDE,(volpan-95)); | |
324 } else if((volpan>=105) && (volpan<=114)) // pitch slide up (105-114) | |
325 { UniVolEffect(VOL_PITCHSLIDEDN,((volpan-105)<<4)); | |
326 } else if((volpan>=115) && (volpan<=124)) // pitch slide down (115-124) | |
327 { UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115)); | |
328 } else if((volpan>=128) && (volpan<=192)) | |
329 { UniVolEffect(VOL_PANNING,((volpan-128) == 64) ? 255 : ((volpan-128) << 2)); | |
330 } else if((volpan>=193) && (volpan<=202)) // portamento to note | |
331 { UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]); | |
332 } else if((volpan>=203) && (volpan<=212)) // vibrato | |
333 { UniVolEffect(VOL_VIBRATO,(volpan-203)); | |
334 } | |
335 | |
336 S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,old_effect); | |
337 | |
338 UniNewline(); | |
339 } | |
340 return UniDup(); | |
341 } | |
342 | |
343 | |
344 int cvt_c5spd_to_finetune(ULONG c5spd, int sampnum) | |
345 { | |
346 int ctmp=0,tmp,note=1,finetune=0; | |
347 | |
348 c5spd/=2; | |
349 | |
350 do | |
351 { tmp = getfrequency(of.flags,getlinearperiod(note,0)); | |
352 if(tmp >= c5spd) break; | |
353 ctmp = tmp; | |
354 note++; | |
355 } while(1); | |
356 | |
357 if(tmp != c5spd) | |
358 { if((tmp-c5spd) < (c5spd-ctmp)) | |
359 while(tmp>c5spd) tmp = getfrequency(of.flags,getlinearperiod(note,--finetune)); | |
360 else | |
361 { note--; | |
362 while(ctmp<c5spd) ctmp = getfrequency(of.flags,getlinearperiod(note,++finetune)); | |
363 } | |
364 } | |
365 | |
366 noteindex[sampnum] = note-48; | |
367 return finetune; | |
368 } | |
369 | |
370 | |
371 BOOL IT_Load(void) | |
372 { | |
373 int t,u,lp; | |
374 INSTRUMENT *d; | |
375 SAMPLE *q; | |
376 | |
377 numtrk = 0; | |
378 | |
379 // try to read module header | |
380 | |
381 _mm_read_I_ULONG(modfp); // kill the 4 byte header | |
382 _mm_read_string(mh->songname,26,modfp); | |
383 _mm_read_UBYTES(mh->blank01,2,modfp); | |
384 mh->ordnum =_mm_read_I_UWORD(modfp); | |
385 mh->insnum =_mm_read_I_UWORD(modfp); | |
386 mh->smpnum =_mm_read_I_UWORD(modfp); | |
387 mh->patnum =_mm_read_I_UWORD(modfp); | |
388 mh->cwt =_mm_read_I_UWORD(modfp); | |
389 mh->cmwt =_mm_read_I_UWORD(modfp); | |
390 mh->flags =_mm_read_I_UWORD(modfp); | |
391 mh->special =_mm_read_I_UWORD(modfp); | |
392 | |
393 mh->globvol =_mm_read_UBYTE(modfp); | |
394 mh->mixvol =_mm_read_UBYTE(modfp); | |
395 mh->initspeed =_mm_read_UBYTE(modfp); | |
396 mh->inittempo =_mm_read_UBYTE(modfp); | |
397 mh->pansep =_mm_read_UBYTE(modfp); | |
398 mh->zerobyte =_mm_read_UBYTE(modfp); | |
399 mh->msglength =_mm_read_I_UWORD(modfp); | |
400 mh->msgoffset =_mm_read_I_ULONG(modfp); | |
401 _mm_read_UBYTES(mh->blank02,4,modfp); | |
402 _mm_read_UBYTES(mh->pantable,64,modfp); | |
403 _mm_read_UBYTES(mh->voltable,64,modfp); | |
404 | |
405 if(feof(modfp)) | |
406 { _mm_errno = MMERR_LOADING_HEADER; | |
407 return 0; | |
408 } | |
409 | |
410 // set module variables | |
411 | |
412 of.modtype = strdup(IT_Version); | |
413 of.modtype[15] = (mh->cwt >> 8) + 0x30; | |
414 of.modtype[17] = ((mh->cwt >> 4) & 0xf) + 0x30; | |
415 of.modtype[18] = ((mh->cwt) & 0xf) + 0x30; | |
416 of.songname = DupStr(mh->songname,26); // make a cstr of songname | |
417 of.reppos = 0; | |
418 of.numpat = mh->patnum; | |
419 of.numins = mh->insnum; | |
420 of.numsmp = mh->smpnum; | |
421 of.initspeed = mh->initspeed; | |
422 of.inittempo = mh->inittempo; | |
423 of.initvolume = mh->globvol; | |
424 | |
425 old_effect = 0; | |
426 if(mh->flags & 8) { of.flags |= (UF_XMPERIODS | UF_LINEAR); old_effect |= 2; } | |
427 if((mh->cwt >= 0x106) && (mh->flags & 16)) old_effect |= 1; | |
428 | |
429 // set panning positions | |
430 for(t=0; t<64; t++) | |
431 { if(mh->pantable[t] < 64) of.panning[t] = mh->pantable[t] << 2; | |
432 else if(mh->pantable[t]==64) of.panning[t] = 255; | |
433 else if(mh->pantable[t]==100) of.panning[t] = PAN_SURROUND; | |
434 } | |
435 | |
436 // set channel volumes | |
437 memcpy(of.chanvol,mh->voltable,64); | |
438 | |
439 // read the order data | |
440 if(!AllocPositions(mh->ordnum)) return 0; | |
441 | |
442 for(t=0; t<mh->ordnum; t++) | |
443 of.positions[t] = _mm_read_UBYTE(modfp); | |
444 | |
445 if(feof(modfp)) | |
446 { _mm_errno = MMERR_LOADING_HEADER; | |
447 return 0; | |
448 } | |
449 | |
450 of.numpos = 0; | |
451 for(t=0; t<mh->ordnum; t++) | |
452 { of.positions[of.numpos] = of.positions[t]; | |
453 poslookup[t] = of.numpos; // bug fix for FREAKY S3Ms / ITs | |
454 if(of.positions[t]<254) of.numpos++; | |
455 } | |
456 | |
457 if((paraptr=(ULONG *)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*sizeof(ULONG))) == NULL) return 0; | |
458 | |
459 // read the instrument, sample, and pattern parapointers | |
460 _mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modfp); | |
461 | |
462 // now is a good time to check if the header was too short :) | |
463 if(feof(modfp)) | |
464 { _mm_errno = MMERR_LOADING_HEADER; | |
465 return 0; | |
466 } | |
467 | |
468 // Check for and load song comment | |
469 if(mh->special & 1) | |
470 { _mm_fseek(modfp,(long)(mh->msgoffset),SEEK_SET); | |
471 if(!ReadComment(mh->msglength)) return 0; | |
472 } | |
473 | |
474 if(!(mh->flags & 4)) of.numins = of.numsmp; | |
475 if(!AllocSamples()) return 0; | |
476 | |
477 if((noteindex=(int *)_mm_malloc(mh->smpnum*sizeof(int)))==NULL) return 0; | |
478 | |
479 q = of.samples; | |
480 | |
481 // Load all samples (they're used either way) | |
482 for(t=0; t<mh->smpnum; t++) | |
483 { ITSAMPLE s; | |
484 | |
485 // seek to sample position | |
486 _mm_fseek(modfp,(long)(paraptr[mh->insnum+t] + 4),SEEK_SET); | |
487 | |
488 // and load sample info | |
489 _mm_read_string(s.filename,12,modfp); | |
490 s.zerobyte = _mm_read_UBYTE(modfp); | |
491 s.globvol = _mm_read_UBYTE(modfp); | |
492 s.flag = _mm_read_UBYTE(modfp); | |
493 s.volume = _mm_read_UBYTE(modfp); | |
494 _mm_read_string(s.sampname,26,modfp); | |
495 s.convert = _mm_read_UBYTE(modfp); | |
496 s.panning = _mm_read_UBYTE(modfp); | |
497 s.length = _mm_read_I_ULONG(modfp); | |
498 s.loopbeg = _mm_read_I_ULONG(modfp); | |
499 s.loopend = _mm_read_I_ULONG(modfp); | |
500 s.c5spd = _mm_read_I_ULONG(modfp); | |
501 s.susbegin = _mm_read_I_ULONG(modfp); | |
502 s.susend = _mm_read_I_ULONG(modfp); | |
503 s.sampoffset = _mm_read_I_ULONG(modfp); | |
504 s.vibspeed = _mm_read_UBYTE(modfp); | |
505 s.vibdepth = _mm_read_UBYTE(modfp); | |
506 s.vibrate = _mm_read_UBYTE(modfp); | |
507 s.vibwave = _mm_read_UBYTE(modfp); | |
508 | |
509 | |
510 // Generate an error if c5spd is > 512k, or samplelength > 256 megs | |
511 // (nothing would EVER be that high) | |
512 | |
513 if(feof(modfp) || (s.c5spd > 0x7ffffL) || (s.length > 0xfffffffUL) || | |
514 (s.loopbeg > 0xfffffffUL) || (s.loopend > 0xfffffffUL)) | |
515 { _mm_errno = MMERR_LOADING_SAMPLEINFO; | |
516 return 0; | |
517 } | |
518 | |
519 q->samplename = DupStr(s.sampname,26); | |
520 | |
521 q->speed = s.c5spd / 2; | |
522 q->panning = ((s.panning & 127)==64) ? 255 : (s.panning & 127) << 2; | |
523 q->length = s.length; | |
524 q->loopstart = s.loopbeg; | |
525 q->loopend = s.loopend; | |
526 q->volume = s.volume; | |
527 q->globvol = s.globvol; | |
528 q->seekpos = s.sampoffset; | |
529 | |
530 // =================================== | |
531 // Convert speed to XM linear finetune | |
532 | |
533 if(of.flags & UF_LINEAR) | |
534 q->speed = cvt_c5spd_to_finetune(s.c5spd, t); | |
535 | |
536 if(s.panning & 128) q->flags |= SF_OWNPAN; | |
537 | |
538 if(s.vibrate) | |
539 { q->vibflags |= AV_IT; | |
540 q->vibtype = s.vibwave; | |
541 q->vibsweep = s.vibrate * 2; | |
542 q->vibdepth = s.vibdepth; | |
543 q->vibrate = s.vibspeed; | |
544 } | |
545 | |
546 if(s.flag & 2) q->flags |= SF_16BITS; | |
547 if(s.flag & 16) q->flags |= SF_LOOP; | |
548 if(s.flag & 64) q->flags |= SF_BIDI; | |
549 | |
550 if(mh->cwt >= 0x200) | |
551 { if(s.convert & 1) q->flags |= SF_SIGNED; | |
552 if(s.convert & 4) q->flags |= SF_DELTA; | |
553 } | |
554 | |
555 q++; | |
556 } | |
557 | |
558 // Load instruments if instrument mode flag enabled | |
559 | |
560 if(mh->flags & 4) | |
561 { if(!AllocInstruments()) return 0; | |
562 d = of.instruments; | |
563 of.flags |= UF_NNA | UF_INST; | |
564 | |
565 for(t=0; t<mh->insnum; t++) | |
566 { ITINSTHEADER ih; | |
567 | |
568 // seek to instrument position | |
569 _mm_fseek(modfp,paraptr[t]+4,SEEK_SET); | |
570 | |
571 // and load instrument info | |
572 _mm_read_string(ih.filename,12,modfp); | |
573 ih.zerobyte = _mm_read_UBYTE(modfp); | |
574 if(mh->cwt < 0x200) // load IT 1.xx inst header | |
575 { ih.volflg = _mm_read_UBYTE(modfp); | |
576 ih.volbeg = _mm_read_UBYTE(modfp); | |
577 ih.volend = _mm_read_UBYTE(modfp); | |
578 ih.volsusbeg = _mm_read_UBYTE(modfp); | |
579 ih.volsusend = _mm_read_UBYTE(modfp); | |
580 _mm_read_I_UWORD(modfp); | |
581 ih.fadeout = _mm_read_I_UWORD(modfp); | |
582 ih.nna = _mm_read_UBYTE(modfp); | |
583 ih.dnc = _mm_read_UBYTE(modfp); | |
584 } else // Read IT200+ header | |
585 { ih.nna = _mm_read_UBYTE(modfp); | |
586 ih.dct = _mm_read_UBYTE(modfp); | |
587 ih.dca = _mm_read_UBYTE(modfp); | |
588 ih.fadeout = _mm_read_I_UWORD(modfp); | |
589 ih.ppsep = _mm_read_UBYTE(modfp); | |
590 ih.ppcenter = _mm_read_UBYTE(modfp); | |
591 ih.globvol = _mm_read_UBYTE(modfp); | |
592 ih.chanpan = _mm_read_UBYTE(modfp); | |
593 ih.rvolvar = _mm_read_UBYTE(modfp); | |
594 ih.rpanvar = _mm_read_UBYTE(modfp); | |
595 } | |
596 | |
597 ih.trkvers = _mm_read_I_UWORD(modfp); | |
598 ih.numsmp = _mm_read_UBYTE(modfp); | |
599 _mm_read_UBYTE(modfp); | |
600 _mm_read_string(ih.name,26,modfp); | |
601 _mm_read_UBYTES(ih.blank01,6,modfp); | |
602 _mm_read_I_UWORDS(ih.samptable,120,modfp); | |
603 if(mh->cwt < 0x200) // load IT 1xx volume envelope | |
604 { _mm_read_UBYTES(ih.volenv,200,modfp); | |
605 for(lp=0; lp<25; lp++) | |
606 { ih.oldvoltick[lp] = _mm_read_UBYTE(modfp); | |
607 ih.volnode[lp] = _mm_read_UBYTE(modfp); | |
608 } | |
609 } else // load IT 2xx vol & chanpan & pitch envs | |
610 { ih.volflg = _mm_read_UBYTE(modfp); | |
611 ih.volpts = _mm_read_UBYTE(modfp); | |
612 ih.volbeg = _mm_read_UBYTE(modfp); | |
613 ih.volend = _mm_read_UBYTE(modfp); | |
614 ih.volsusbeg = _mm_read_UBYTE(modfp); | |
615 ih.volsusend = _mm_read_UBYTE(modfp); | |
616 for(lp=0; lp<25; lp++) | |
617 { ih.volnode[lp] = _mm_read_UBYTE(modfp); | |
618 ih.voltick[lp] = _mm_read_I_UWORD(modfp); | |
619 } | |
620 _mm_read_UBYTE(modfp); | |
621 | |
622 ih.panflg = _mm_read_UBYTE(modfp); | |
623 ih.panpts = _mm_read_UBYTE(modfp); | |
624 ih.panbeg = _mm_read_UBYTE(modfp); | |
625 ih.panend = _mm_read_UBYTE(modfp); | |
626 ih.pansusbeg = _mm_read_UBYTE(modfp); | |
627 ih.pansusend = _mm_read_UBYTE(modfp); | |
628 for(lp=0; lp<25; lp++) | |
629 { ih.pannode[lp] = _mm_read_SBYTE(modfp); | |
630 ih.pantick[lp] = _mm_read_I_UWORD(modfp); | |
631 } | |
632 _mm_read_UBYTE(modfp); | |
633 | |
634 ih.pitflg = _mm_read_UBYTE(modfp); | |
635 ih.pitpts = _mm_read_UBYTE(modfp); | |
636 ih.pitbeg = _mm_read_UBYTE(modfp); | |
637 ih.pitend = _mm_read_UBYTE(modfp); | |
638 ih.pitsusbeg = _mm_read_UBYTE(modfp); | |
639 ih.pitsusend = _mm_read_UBYTE(modfp); | |
640 for(lp=0; lp<25; lp++) | |
641 { ih.pitnode[lp] = _mm_read_SBYTE(modfp); | |
642 ih.pittick[lp] = _mm_read_I_UWORD(modfp); | |
643 } | |
644 _mm_read_UBYTE(modfp); | |
645 } | |
646 | |
647 if(feof(modfp)) | |
648 { _mm_errno = MMERR_LOADING_SAMPLEINFO; | |
649 return 0; | |
650 } | |
651 | |
652 d->volflg |= EF_VOLENV; | |
653 d->insname = DupStr(ih.name,26); | |
654 d->nnatype = ih.nna; | |
655 | |
656 if(mh->cwt < 0x200) | |
657 { d->volfade = ih.fadeout << 6; | |
658 if(ih.dnc) | |
659 { d->dct = DCT_NOTE; | |
660 d->dca = DCA_CUT; | |
661 } | |
662 | |
663 if(ih.volflg & 1) d->volflg |= EF_ON; | |
664 if(ih.volflg & 2) d->volflg |= EF_LOOP; | |
665 if(ih.volflg & 4) d->volflg |= EF_SUSTAIN; | |
666 | |
667 // XM conversion of IT envelope Array | |
668 | |
669 d->volbeg = ih.volbeg; | |
670 d->volend = ih.volend; | |
671 d->volsusbeg = ih.volsusbeg; | |
672 d->volsusend = ih.volsusend; | |
673 | |
674 if(ih.volflg & 1) | |
675 { for(u=0; u<25; u++) | |
676 if(ih.oldvoltick[d->volpts] != 0xff) | |
677 { d->volenv[d->volpts].val = (ih.volnode[d->volpts] << 2); | |
678 d->volenv[d->volpts].pos = ih.oldvoltick[d->volpts]; | |
679 d->volpts++; | |
680 } else break; | |
681 } | |
682 } else | |
683 { d->panning = ((ih.chanpan&127) == 64) ? 255 : (ih.chanpan&127)<<2; | |
684 if(!(ih.chanpan & 128)) d->flags |= IF_OWNPAN; | |
685 | |
686 if(!(ih.ppsep & 128)) | |
687 { d->pitpansep = ih.ppsep << 2; | |
688 d->pitpancenter= ih.ppcenter; | |
689 d->flags |= IF_PITCHPAN; | |
690 } | |
691 d->globvol = ih.globvol >> 1; | |
692 d->volfade = ih.fadeout << 5; | |
693 d->dct = ih.dct; | |
694 d->dca = ih.dca; | |
695 | |
696 if(mh->cwt >= 0x204) | |
697 { d->rvolvar = ih.rvolvar; | |
698 d->rpanvar = ih.rpanvar; | |
699 } | |
700 | |
701 if(ih.volflg & 1) d->volflg |= EF_ON; | |
702 if(ih.volflg & 2) d->volflg |= EF_LOOP; | |
703 if(ih.volflg & 4) d->volflg |= EF_SUSTAIN; | |
704 | |
705 if(ih.panflg & 1) d->panflg |= EF_ON; | |
706 if(ih.panflg & 2) d->panflg |= EF_LOOP; | |
707 if(ih.panflg & 4) d->panflg |= EF_SUSTAIN; | |
708 | |
709 if(ih.pitflg & 1) d->pitflg |= EF_ON; | |
710 if(ih.pitflg & 2) d->pitflg |= EF_LOOP; | |
711 if(ih.pitflg & 4) d->pitflg |= EF_SUSTAIN; | |
712 | |
713 d->volpts = ih.volpts; | |
714 d->volbeg = ih.volbeg; | |
715 d->volend = ih.volend; | |
716 d->volsusbeg = ih.volsusbeg; | |
717 d->volsusend = ih.volsusend; | |
718 | |
719 for(u=0; u<ih.volpts; u++) | |
720 { d->volenv[u].val = (ih.volnode[u] << 2); | |
721 d->volenv[u].pos = ih.voltick[u]; | |
722 } | |
723 | |
724 d->panpts = ih.panpts; | |
725 d->panbeg = ih.panbeg; | |
726 d->panend = ih.panend; | |
727 d->pansusbeg = ih.pansusbeg; | |
728 d->pansusend = ih.pansusend; | |
729 | |
730 for(u=0; u<ih.panpts; u++) | |
731 { d->panenv[u].val = (ih.pannode[u]+32) << 2; | |
732 d->panenv[u].pos = ih.pantick[u]; | |
733 } | |
734 | |
735 d->pitpts = ih.pitpts; | |
736 d->pitbeg = ih.pitbeg; | |
737 d->pitend = ih.pitend; | |
738 d->pitsusbeg = ih.pitsusbeg; | |
739 d->pitsusend = ih.pitsusend; | |
740 | |
741 for(u=0; u<ih.pitpts; u++) | |
742 { d->pitenv[u].val = (ih.pitnode[u]+32); | |
743 d->pitenv[u].pos = ih.pittick[u]; | |
744 } | |
745 } | |
746 | |
747 if(of.flags & UF_LINEAR) | |
748 { for(u=0; u<120; u++) | |
749 { d->samplenote[u] = (ih.samptable[u] & 255); | |
750 d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255; | |
751 if(d->samplenumber[u]!=255) | |
752 d->samplenote[u] += noteindex[d->samplenumber[u]]; | |
753 } | |
754 } else | |
755 { for(u=0; u<120; u++) | |
756 { d->samplenote[u] = (ih.samptable[u] & 255); | |
757 d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255; | |
758 } | |
759 } | |
760 | |
761 d++; | |
762 } | |
763 } else if(of.flags & UF_LINEAR) | |
764 { if(!AllocInstruments()) return 0; | |
765 d = of.instruments; | |
766 of.flags |= UF_INST; | |
767 | |
768 for(t=0; t<mh->smpnum; t++, d++) | |
769 { for(u=0; u<120; u++) | |
770 d->samplenote[u] += noteindex[d->samplenumber[u]]; | |
771 } | |
772 } | |
773 | |
774 | |
775 // Figure out how many channels this blasted song actually uses (what | |
776 // ever happened to common courtesy of storing this simple value | |
777 // somewhere in the damn module, eh!?) | |
778 | |
779 of.numchn = 0; | |
780 memset(remap,-1,64*sizeof(UBYTE)); | |
781 | |
782 for(t=0; t<of.numpat; t++) | |
783 { UWORD packlen; | |
784 | |
785 // seek to pattern position | |
786 if(paraptr[mh->insnum+mh->smpnum+t] != 0) // No parapointer = pattern of 64 rows, EMPTY | |
787 { _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET); | |
788 packlen = _mm_read_I_UWORD(modfp); | |
789 packlen = _mm_read_I_UWORD(modfp); // read pattern length (# of rows) | |
790 _mm_read_I_ULONG(modfp); | |
791 if(IT_GetNumChannels(packlen)) return 0; | |
792 } | |
793 } | |
794 | |
795 // give each of them a different number | |
796 for(t=0; t<64; t++) | |
797 { if(remap[t]==0) | |
798 { remap[t] = of.numchn; | |
799 of.numchn++; | |
800 } | |
801 } | |
802 | |
803 of.numtrk = of.numpat*of.numchn; | |
804 | |
805 | |
806 if(!AllocPatterns()) return 0; | |
807 if(!AllocTracks()) return 0; | |
808 | |
809 for(t=0; t<of.numpat; t++) | |
810 { UWORD packlen; | |
811 | |
812 // seek to pattern position | |
813 if(paraptr[mh->insnum+mh->smpnum+t] == 0) // No parapointer = pattern of 64 rows, EMPTY | |
814 { of.pattrows[t] = 64; | |
815 for(u=0; u<of.numchn; u++) | |
816 { int k; | |
817 UniReset(); | |
818 for(k=0; k<64; k++) UniNewline(); | |
819 of.tracks[numtrk++] = UniDup(); | |
820 } | |
821 } else | |
822 { _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET); | |
823 packlen = _mm_read_I_UWORD(modfp); | |
824 of.pattrows[t] = _mm_read_I_UWORD(modfp); | |
825 _mm_read_I_ULONG(modfp); | |
826 | |
827 if(!IT_ReadPattern(of.pattrows[t])) return 0; | |
828 } | |
829 } | |
830 | |
831 return 1; | |
832 } | |
833 | |
834 | |
835 CHAR *IT_LoadTitle(void) | |
836 { | |
837 CHAR s[26]; | |
838 | |
839 _mm_fseek(modfp,4,SEEK_SET); | |
840 if(!fread(s,26,1,modfp)) return NULL; | |
841 | |
842 return(DupStr(s,26)); | |
843 } | |
844 | |
845 | |
846 MLOADER load_it = | |
847 { NULL, | |
848 "IT", | |
849 "Portable IT loader v0.2", | |
850 IT_Init, | |
851 IT_Test, | |
852 IT_Load, | |
853 IT_Cleanup, | |
854 | |
855 IT_LoadTitle | |
856 }; | |
857 |